home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / Filezilla Server / FileZilla_Server-0_9_41.exe / source / ControlSocket.cpp < prev    next >
C/C++ Source or Header  |  2012-02-26  |  99KB  |  3,715 lines

  1. // FileZilla Server - a Windows ftp server
  2.  
  3. // Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
  4.  
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9.  
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14.  
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. // ControlSocket.cpp: Implementierungsdatei
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "ControlSocket.h"
  24. #include "transfersocket.h"
  25. #include "ServerThread.h"
  26. #include "Options.h"
  27. #include "Permissions.h"
  28. #include "AsyncGssSocketLayer.h"
  29. #include "AsyncSslSocketLayer.h"
  30. #include <math.h>
  31. #include "iputils.h"
  32. #include "autobanmanager.h"
  33.  
  34. #ifdef _DEBUG
  35. #undef THIS_FILE
  36. static char THIS_FILE[] = __FILE__;
  37. #endif
  38.  
  39. /////////////////////////////////////////////////////////////////////////////
  40. // CControlSocket
  41.  
  42. std::map<CStdString, int> CControlSocket::m_UserCount;
  43. CCriticalSectionWrapper CControlSocket::m_Sync;
  44.  
  45. CControlSocket::CControlSocket(CServerThread *pOwner)
  46.     : m_hash_algorithm(CHashThread::SHA1)
  47. {
  48.     m_status.loggedon = FALSE;
  49.     m_status.hammerValue = 0;
  50.     m_transferstatus.socket = NULL;
  51.     m_transferstatus.ip = _T("");
  52.     m_transferstatus.port = -1;
  53.     m_transferstatus.pasv = -1;
  54.     m_transferstatus.rest = 0;
  55.     m_transferstatus.type = -1;
  56.     m_transferstatus.family = AF_UNSPEC;
  57.     m_bWaitGoOffline = FALSE;
  58.     GetSystemTime(&m_LastTransferTime);
  59.     GetSystemTime(&m_LastCmdTime);
  60.     GetSystemTime(&m_LoginTime);
  61.     m_bQuitCommand = FALSE;
  62.  
  63.     ASSERT(pOwner);
  64.     m_pOwner = pOwner;
  65.  
  66.     m_nTelnetSkip = 0;
  67.     m_nRecvBufferPos = 0;
  68.  
  69.     m_pSendBuffer = NULL;
  70.     m_nSendBufferLen = 0;
  71.  
  72.     m_pGssLayer = NULL;
  73.     m_pSslLayer = NULL;
  74.  
  75.     for (int i = 0; i < 2; i++)
  76.     {
  77.         m_SlQuotas[i].bContinue = false;
  78.         m_SlQuotas[i].nBytesAllowedToTransfer = -1;
  79.         m_SlQuotas[i].nTransferred = 0;
  80.         m_SlQuotas[i].bBypassed = true;
  81.     }
  82.  
  83.     m_transferMode = mode_stream;
  84.  
  85.     m_zlibLevel = 8;
  86.  
  87.     m_antiHammeringWaitTime = 0;
  88.     m_bProtP = false;
  89.  
  90.     m_useUTF8 = true;
  91.  
  92.     for (int i = 0; i < 3; i++)
  93.         m_facts[i] = true;
  94.     m_facts[fact_perm] = false;
  95.  
  96.     m_shutdown = false;
  97.  
  98.     m_hash_id = 0;
  99. }
  100.  
  101. CControlSocket::~CControlSocket()
  102. {
  103.     if (m_status.loggedon)
  104.     {
  105.         DecUserCount(m_status.user);
  106.         m_pOwner->DecIpCount(m_status.ip);
  107.         m_status.loggedon = FALSE;
  108.     }
  109.     t_connop *op = new t_connop;
  110.     op->data = 0;
  111.     op->op = USERCONTROL_CONNOP_REMOVE;
  112.     op->userid = m_userid;
  113.     m_pOwner->SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  114.     if (m_transferstatus.socket)
  115.         delete m_transferstatus.socket;
  116.     m_transferstatus.socket=0;
  117.  
  118.     delete [] m_pSendBuffer;
  119.     m_nSendBufferLen = 0;
  120.  
  121.     RemoveAllLayers();
  122.     delete m_pGssLayer;
  123.     delete m_pSslLayer;
  124. }
  125.  
  126. /////////////////////////////////////////////////////////////////////////////
  127. // Member-Funktion CControlSocket
  128.  
  129. #define BUFFERSIZE 500
  130. void CControlSocket::OnReceive(int nErrorCode)
  131. {
  132.     if (m_antiHammeringWaitTime)
  133.     {
  134.         if (nErrorCode)
  135.         {
  136.             //Control connection has been closed
  137.             Close();
  138.             SendStatus(_T("disconnected."), 0);
  139.             m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  140.         }
  141.         return;
  142.     }
  143.  
  144.     int len = BUFFERSIZE;
  145.     long long nLimit = GetSpeedLimit(upload);
  146.     if (!nLimit)
  147.     {
  148.         ParseCommand();
  149.         return;
  150.     }
  151.     if (len > nLimit && nLimit != -1)
  152.         len = static_cast<int>(nLimit);
  153.  
  154.     unsigned char *buffer = new unsigned char[BUFFERSIZE];
  155.     int numread = Receive(buffer, len);
  156.     if (numread != SOCKET_ERROR && numread)
  157.     {
  158.         if (nLimit != -1)
  159.             m_SlQuotas[upload].nTransferred += numread;
  160.  
  161.         m_pOwner->IncRecvCount(numread);
  162.         //Parse all received bytes
  163.         for (int i = 0; i < numread; i++)
  164.         {
  165.             if (!m_nRecvBufferPos)
  166.             {
  167.                 //Remove telnet characters
  168.                 if (m_nTelnetSkip)
  169.                 {
  170.                     if (buffer[i] < 240)
  171.                         m_nTelnetSkip = 0;
  172.                     else
  173.                         continue;
  174.                 }
  175.                 else if (buffer[i] == 255)
  176.                 {
  177.                     m_nTelnetSkip = 1;
  178.                     continue;
  179.                 }
  180.             }
  181.  
  182.             //Check for line endings
  183.             if ((buffer[i] == '\r')||(buffer[i] == 0)||(buffer[i] == '\n'))
  184.             {
  185.                 //If input buffer is not empty...
  186.                 if (m_nRecvBufferPos)
  187.                 {
  188.                     m_RecvBuffer[m_nRecvBufferPos] = 0;
  189.                     m_RecvLineBuffer.push_back(m_RecvBuffer);
  190.                     m_nRecvBufferPos = 0;
  191.  
  192.                     //Signal that there is a new command waiting to be processed.
  193.                     GetSystemTime(&m_LastCmdTime);
  194.                 }
  195.             }
  196.             else
  197.                 //The command may only be 2000 chars long. This ensures that a malicious user can't
  198.                 //send extremely large commands to fill the memory of the server
  199.                 if (m_nRecvBufferPos < 2000)
  200.                     m_RecvBuffer[m_nRecvBufferPos++] = buffer[i];
  201.         }
  202.     }
  203.     else
  204.     {
  205.         if (!numread || GetLastError() != WSAEWOULDBLOCK)
  206.         {
  207.             //Control connection has been closed
  208.             Close();
  209.             SendStatus(_T("disconnected."), 0);
  210.             m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  211.  
  212.             delete [] buffer;
  213.             return;
  214.         }
  215.     }
  216.  
  217.     ParseCommand();
  218.  
  219.     delete [] buffer;
  220. }
  221.  
  222. BOOL CControlSocket::GetCommand(CStdString &command, CStdString &args)
  223. {
  224.     //Get first command from input buffer
  225.     CStdStringA str;
  226.     if (m_RecvLineBuffer.empty())
  227.         return FALSE;
  228.     str = m_RecvLineBuffer.front();
  229.     m_RecvLineBuffer.pop_front();
  230.  
  231.     //Output command in status window
  232.     CStdString str2;
  233.     if (m_useUTF8)
  234.     {
  235. #ifdef _UNICODE
  236.     str2 = ConvFromNetwork(str);
  237. #else
  238.     str2 = ConvToLocal(ConvFromNetwork(str));
  239. #endif
  240.     }
  241.     else
  242.     {
  243. #ifdef _UNICODE
  244.     str2 = ConvFromLocal(str);
  245. #else
  246.     str2 = str;
  247. #endif
  248.     }
  249.     
  250.     //Hide passwords if the server admin wants to.
  251.     if (!str2.Left(5).CompareNoCase(_T("PASS ")))
  252.     {    if (m_pOwner->m_pOptions->GetOptionVal(OPTION_LOGSHOWPASS))
  253.             SendStatus(str2, 2);
  254.         else
  255.         {
  256.             CStdString msg = str2;
  257.             for (int i = 5; i < msg.GetLength(); i++)
  258.                 msg[i] = '*';
  259.             SendStatus(msg, 2);
  260.         }
  261.     }
  262.     else
  263.         SendStatus(str2, 2);
  264.  
  265.     //Split command and arguments
  266.     int pos = str2.Find(_T(" "));
  267.     if (pos != -1)
  268.     {
  269.         command = str2.Left(pos);
  270.         if (pos == str2.GetLength() - 1)
  271.             args = _T("");
  272.         else
  273.         {
  274.             args = str2.Mid(pos + 1);
  275.             if (args == _T(""))
  276.             {
  277.                 Send(_T("501 Syntax error, failed to decode string"));
  278.                 return FALSE;
  279.             }
  280.         }
  281.     }
  282.     else
  283.     {
  284.         args = _T("");
  285.         command = str2;
  286.     }
  287.     if (command == _T(""))
  288.         return FALSE;
  289.     command.MakeUpper();
  290.     return TRUE;
  291. }
  292.  
  293. void CControlSocket::SendStatus(LPCTSTR status, int type)
  294. {
  295.     t_statusmsg *msg = new t_statusmsg;
  296.     _tcscpy(msg->ip, m_RemoteIP);
  297.     GetLocalTime(&msg->time);
  298.     if (!m_status.loggedon)
  299.     {
  300.         msg->user = new TCHAR[16];
  301.         _tcscpy(msg->user, _T("(not logged in)"));
  302.     }
  303.     else
  304.     {
  305.         msg->user = new TCHAR[_tcslen(m_status.user) + 1];
  306.         _tcscpy(msg->user, m_status.user);
  307.     }
  308.     msg->userid = m_userid;
  309.     msg->type = type;
  310.     msg->status = new TCHAR[_tcslen(status) + 1];
  311.     _tcscpy(msg->status, status);
  312.     m_pOwner->SendNotification(FSM_STATUSMESSAGE, (LPARAM)msg);
  313. }
  314.  
  315. BOOL CControlSocket::Send(LPCTSTR str, bool sendStatus /*=true*/)
  316. {
  317.     if (sendStatus)
  318.         SendStatus(str, 3);
  319.  
  320.     char* buffer;
  321.     int len;
  322.     if (m_useUTF8)
  323.     {
  324.         char* utf8 = ConvToNetwork(str);
  325.         if (!utf8)
  326.         {
  327.             Close();
  328.             SendStatus(_T("Failed to convert reply to UTF-8"), 1);
  329.             m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  330.  
  331.             return false;
  332.         }
  333.  
  334.         buffer = new char[strlen(utf8) + 3];
  335.         strcpy(buffer, utf8);
  336.         strcat(buffer, "\r\n");
  337.         len = strlen(buffer);
  338.         delete [] utf8;
  339.     }
  340.     else
  341.     {
  342.         CStdStringA local = ConvToLocal(str);
  343.         if (local == "")
  344.         {
  345.             Close();
  346.             SendStatus(_T("Failed to convert reply to local charset"), 1);
  347.             m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  348.  
  349.             return false;
  350.         }
  351.  
  352.         buffer = new char[strlen(local) + 3];
  353.         strcpy(buffer, local);
  354.         strcat(buffer, "\r\n");
  355.         len = strlen(buffer);
  356.     }
  357.  
  358.  
  359.     //Add line to back of send buffer if it's not empty
  360.     if (m_pSendBuffer)
  361.     {
  362.         char *tmp = m_pSendBuffer;
  363.         m_pSendBuffer = new char[m_nSendBufferLen + len];
  364.         memcpy(m_pSendBuffer, tmp, m_nSendBufferLen);
  365.         memcpy(m_pSendBuffer+m_nSendBufferLen, buffer, len);
  366.         delete [] tmp;
  367.         m_nSendBufferLen += len;
  368.         delete [] buffer;
  369.         return TRUE;
  370.     }
  371.  
  372.     long long nLimit = GetSpeedLimit(download);
  373.     if (!nLimit)
  374.     {
  375.         if (!m_pSendBuffer)
  376.         {
  377.             m_pSendBuffer = buffer;
  378.             m_nSendBufferLen = len;
  379.         }
  380.         else
  381.         {
  382.             char *tmp = m_pSendBuffer;
  383.             m_pSendBuffer = new char[m_nSendBufferLen + len];
  384.             memcpy(m_pSendBuffer, tmp, m_nSendBufferLen);
  385.             memcpy(m_pSendBuffer+m_nSendBufferLen, buffer, len);
  386.             delete [] tmp;
  387.             m_nSendBufferLen += len;
  388.             delete [] buffer;
  389.         }
  390.         return TRUE;
  391.     }
  392.     int numsend = len;
  393.     if (nLimit != -1 && numsend > nLimit)
  394.         numsend = static_cast<int>(nLimit);
  395.  
  396.     int res = CAsyncSocketEx::Send(buffer, numsend);
  397.     if (res==SOCKET_ERROR && GetLastError() == WSAEWOULDBLOCK)
  398.     {
  399.         res = 0;
  400.     }
  401.     else if (!res || res==SOCKET_ERROR)
  402.     {
  403.         delete [] buffer;
  404.         Close();
  405.         SendStatus(_T("could not send reply, disconnected."), 0);
  406.         m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  407.         return FALSE;
  408.     }
  409.  
  410.     if (nLimit != -1)
  411.         m_SlQuotas[download].nTransferred += res;
  412.  
  413.     if (res != len)
  414.     {
  415.         if (!m_pSendBuffer)
  416.         {
  417.             m_pSendBuffer = new char[len-res];
  418.             memcpy(m_pSendBuffer, buffer+res, len-res);
  419.             m_nSendBufferLen = len-res;
  420.         }
  421.         else
  422.         {
  423.             char *tmp = m_pSendBuffer;
  424.             m_pSendBuffer = new char[m_nSendBufferLen + len - res];
  425.             memcpy(m_pSendBuffer, tmp, m_nSendBufferLen);
  426.             memcpy(m_pSendBuffer+m_nSendBufferLen, buffer+res, len-res);
  427.             delete [] tmp;
  428.             m_nSendBufferLen += len-res;
  429.         }
  430.         TriggerEvent(FD_WRITE);
  431.     }
  432.     delete [] buffer;
  433.  
  434.     m_pOwner->IncSendCount(res);
  435.     return TRUE;
  436. }
  437.  
  438. void CControlSocket::OnClose(int nErrorCode)
  439. {
  440.     Close();
  441.     SendStatus(_T("disconnected."), 0);
  442.     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  443.     CAsyncSocketEx::OnClose(nErrorCode);
  444. }
  445.  
  446. #define COMMAND_USER    0
  447. #define COMMAND_PASS    1
  448. #define COMMAND_QUIT    2
  449. #define COMMAND_CWD        3
  450. #define COMMAND_PWD        4
  451. #define COMMAND_PORT    5
  452. #define COMMAND_PASV    6
  453. #define COMMAND_TYPE    7
  454. #define COMMAND_LIST    8
  455. #define COMMAND_REST    9
  456. #define COMMAND_CDUP    10
  457. #define COMMAND_RETR    11
  458. #define COMMAND_STOR    12
  459. #define COMMAND_SIZE    13
  460. #define COMMAND_DELE    14
  461. #define COMMAND_RMD        15
  462. #define COMMAND_MKD        16
  463. #define COMMAND_RNFR    17
  464. #define COMMAND_RNTO    18
  465. #define COMMAND_ABOR    19
  466. #define COMMAND_SYST    20
  467. #define COMMAND_NOOP    21
  468. #define COMMAND_APPE    22
  469. #define COMMAND_NLST    23
  470. #define COMMAND_MDTM    24
  471. #define COMMAND_XPWD    25
  472. #define COMMAND_XCUP    26
  473. #define COMMAND_XMKD    27
  474. #define COMMAND_XRMD    28
  475. #define COMMAND_NOP        29
  476. #define COMMAND_EPSV    30
  477. #define COMMAND_EPRT    31
  478. #define COMMAND_AUTH    32
  479. #define COMMAND_ADAT    33
  480. #define COMMAND_PBSZ    34
  481. #define COMMAND_PROT    35
  482. #define COMMAND_FEAT    36
  483. #define COMMAND_MODE    37
  484. #define COMMAND_OPTS    38
  485. #define COMMAND_HELP    39
  486. #define COMMAND_ALLO    40
  487. #define COMMAND_MLST    41
  488. #define COMMAND_MLSD    42
  489. #define COMMAND_SITE    43
  490. #define COMMAND_PASVSMC    44 // some bugged SMC routers convert incoming PASV into P@SW
  491. #define COMMAND_STRU    45
  492. #define COMMAND_CLNT    46
  493. #define COMMAND_MFMT    47
  494. #define COMMAND_HASH    48
  495.  
  496. typedef struct
  497. {
  498.     int nID;
  499.     TCHAR command[5];
  500.     BOOL bHasargs;
  501.     BOOL bValidBeforeLogon;
  502. } t_command;
  503.  
  504. static const t_command commands[]={    COMMAND_USER, _T("USER"), TRUE,     TRUE,
  505.                                     COMMAND_PASS, _T("PASS"), FALSE, TRUE,
  506.                                     COMMAND_QUIT, _T("QUIT"), FALSE, TRUE,
  507.                                     COMMAND_CWD,  _T("CWD"),  FALSE, FALSE,
  508.                                     COMMAND_PWD,  _T("PWD"),  FALSE, FALSE,
  509.                                     COMMAND_PORT, _T("PORT"), TRUE,  FALSE,
  510.                                     COMMAND_PASV, _T("PASV"), FALSE, FALSE,
  511.                                     COMMAND_TYPE, _T("TYPE"), TRUE,  FALSE,
  512.                                     COMMAND_LIST, _T("LIST"), FALSE, FALSE,
  513.                                     COMMAND_REST, _T("REST"), TRUE,  FALSE,
  514.                                     COMMAND_CDUP, _T("CDUP"), FALSE, FALSE,
  515.                                     COMMAND_RETR, _T("RETR"), TRUE,  FALSE,
  516.                                     COMMAND_STOR, _T("STOR"), TRUE,  FALSE,
  517.                                     COMMAND_SIZE, _T("SIZE"), TRUE,  FALSE,
  518.                                     COMMAND_DELE, _T("DELE"), TRUE,  FALSE,
  519.                                     COMMAND_RMD,  _T("RMD"),  TRUE,  FALSE,
  520.                                     COMMAND_MKD,  _T("MKD"),  TRUE,  FALSE,
  521.                                     COMMAND_RNFR, _T("RNFR"), TRUE,  FALSE,
  522.                                     COMMAND_RNTO, _T("RNTO"), TRUE,  FALSE,
  523.                                     COMMAND_ABOR, _T("ABOR"), FALSE, FALSE,
  524.                                     COMMAND_SYST, _T("SYST"), FALSE, TRUE,
  525.                                     COMMAND_NOOP, _T("NOOP"), FALSE, FALSE,
  526.                                     COMMAND_APPE, _T("APPE"), TRUE,  FALSE,
  527.                                     COMMAND_NLST, _T("NLST"), FALSE, FALSE,
  528.                                     COMMAND_MDTM, _T("MDTM"), TRUE,  FALSE,
  529.                                     COMMAND_XPWD, _T("XPWD"), FALSE, FALSE,
  530.                                     COMMAND_XCUP, _T("XCUP"), FALSE, FALSE,
  531.                                     COMMAND_XMKD, _T("XMKD"), TRUE,  FALSE,
  532.                                     COMMAND_XRMD, _T("XRMD"), TRUE,  FALSE,
  533.                                     COMMAND_NOP,  _T("NOP"),  FALSE, FALSE,
  534.                                     COMMAND_EPSV, _T("EPSV"), FALSE, FALSE,
  535.                                     COMMAND_EPRT, _T("EPRT"), TRUE,  FALSE,
  536.                                     COMMAND_AUTH, _T("AUTH"), TRUE,  TRUE,
  537.                                     COMMAND_ADAT, _T("ADAT"), TRUE,  TRUE,
  538.                                     COMMAND_PBSZ, _T("PBSZ"), TRUE,  TRUE,
  539.                                     COMMAND_PROT, _T("PROT"), TRUE,  TRUE,
  540.                                     COMMAND_FEAT, _T("FEAT"), FALSE, TRUE,
  541.                                     COMMAND_MODE, _T("MODE"), TRUE,  FALSE,
  542.                                     COMMAND_OPTS, _T("OPTS"), TRUE,  FALSE,
  543.                                     COMMAND_HELP, _T("HELP"), FALSE, TRUE,
  544.                                     COMMAND_ALLO, _T("ALLO"), FALSE, FALSE,
  545.                                     COMMAND_MLST, _T("MLST"), FALSE, FALSE,
  546.                                     COMMAND_MLSD, _T("MLSD"), FALSE, FALSE,
  547.                                     COMMAND_SITE, _T("SITE"), TRUE,  TRUE,
  548.                                     COMMAND_PASVSMC, _T("P@SW"), FALSE, FALSE,
  549.                                     COMMAND_STRU, _T("STRU"), TRUE, FALSE,
  550.                                     COMMAND_CLNT, _T("CLNT"), TRUE, TRUE,
  551.                                     COMMAND_MFMT, _T("MFMT"), TRUE, FALSE,
  552.                                     COMMAND_HASH, _T("HASH"), TRUE, FALSE
  553.                         };
  554.  
  555. void CControlSocket::ParseCommand()
  556. {
  557.     if (m_antiHammeringWaitTime)
  558.         return;
  559.  
  560.     //Get command
  561.     CStdString command;
  562.     CStdString args;
  563.     if (!GetCommand(command, args))
  564.         return;
  565.  
  566.     //Check if command is valid
  567.     int nCommandID = -1;
  568.     for (int i = 0; i < (sizeof(commands)/sizeof(t_command)); i++)
  569.     {
  570.         if (command == commands[i].command)
  571.         {
  572.             //Does the command needs an argument?
  573.             if (commands[i].bHasargs && (args == _T("")))
  574.             {
  575.                 Send(_T("501 Syntax error"));
  576.                 if (!m_RecvLineBuffer.empty())
  577.                     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_COMMAND, m_userid);
  578.                 return;
  579.             }
  580.             //Can it be issued before logon?
  581.             else if (!m_status.loggedon && !commands[i].bValidBeforeLogon)
  582.             {
  583.                 Send(_T("530 Please log in with USER and PASS first."));
  584.                 if (!m_RecvLineBuffer.empty())
  585.                     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_COMMAND, m_userid);
  586.                 return;
  587.             }
  588.             nCommandID = commands[i].nID;
  589.             break;
  590.         }
  591.     }
  592.     //Command not recognized
  593.     if (nCommandID == -1)
  594.     {
  595.         Send(_T("500 Syntax error, command unrecognized."));
  596.         if (!m_RecvLineBuffer.empty())
  597.             m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_COMMAND, m_userid);
  598.         return;
  599.     }
  600.  
  601.     //Now process the commands
  602.     switch (nCommandID)
  603.     {
  604.     case COMMAND_USER:
  605.         {
  606.             AntiHammerIncrease();
  607.  
  608.             if (m_status.loggedon)
  609.             {
  610.                 GetSystemTime(&m_LoginTime);
  611.                 DecUserCount(m_status.user);
  612.                 m_pOwner->DecIpCount(m_status.ip);
  613.                 t_connop *op = new t_connop;
  614.                 op->op = USERCONTROL_CONNOP_CHANGEUSER;
  615.                 t_connectiondata_changeuser *conndata = new t_connectiondata_changeuser;
  616.                 op->data = conndata;
  617.                 op->userid = m_userid;
  618.                 m_pOwner->SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  619.  
  620.                 m_status.loggedon = FALSE;
  621.                 m_CurrentServerDir = _T("");
  622.             }
  623.             if (m_pOwner->m_pOptions->GetOptionVal(OPTION_ENABLESSL) && m_pOwner->m_pOptions->GetOptionVal(OPTION_ALLOWEXPLICITSSL) &&
  624.                 m_pOwner->m_pOptions->GetOptionVal(OPTION_SSLFORCEEXPLICIT) && !m_pSslLayer)
  625.             {
  626.                 Send(_T("530 Have to use explicit SSL/TLS before logging on."));
  627.                 break;
  628.             }
  629.             RenName = _T("");
  630.             args.MakeLower();
  631.             m_status.user = args;
  632.             if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
  633.             {
  634.                 char sendme[4096];
  635.  
  636. #ifdef _UNICODE
  637.                 int res = m_pGssLayer->ProcessCommand("USER", ConvToLocal(args), sendme);
  638. #else
  639.                 int res = m_pGssLayer->ProcessCommand("USER", args, sendme);
  640. #endif
  641.                 if (res != -1)
  642.                 {
  643.                     if (DoUserLogin(0, true))
  644.                     {
  645. #ifdef _UNICODE
  646.                         Send(ConvFromLocal(sendme));
  647. #else
  648.                         Send(sendme);
  649. #endif
  650.                     }
  651.                     else
  652.                         m_status.user = _T("");
  653.                 }
  654.                 break;
  655.             }
  656.             if (!m_pSslLayer)
  657.             {
  658.                 CUser user;
  659.                 if (m_pOwner->m_pPermissions->CheckUserLogin(m_status.user, _T(""), user, true) && user.ForceSsl())
  660.                 {
  661.                     m_status.user = _T("");
  662.                     Send(_T("530 SSL required"));
  663.                     break;
  664.                 }
  665.             }
  666.             Send(_T("331 Password required for ") + args);
  667.         }
  668.         break;
  669.     case COMMAND_PASS:
  670.         AntiHammerIncrease();
  671.  
  672.         if (m_status.loggedon)
  673.             Send(_T("503 Bad sequence of commands."));
  674.         else if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
  675.         {
  676.             char sendme[4096];
  677. #ifdef _UNICODE
  678.             int res = m_pGssLayer->ProcessCommand("PASS", ConvToLocal(m_status.user), ConvToLocal(args), sendme);
  679. #else
  680.             int res = m_pGssLayer->ProcessCommand("PASS", m_status.user, args, sendme);
  681. #endif
  682.  
  683.             if (res != -1)
  684.             {
  685.                 if (DoUserLogin(_T(""), true))
  686. #ifdef _UNICODE
  687.                     Send(ConvFromLocal(sendme));
  688. #else
  689.                     Send(sendme);
  690. #endif
  691.             }
  692.         }
  693.         else if (DoUserLogin(args))
  694.             Send(_T("230 Logged on"));
  695.         break;
  696.     case COMMAND_QUIT:
  697.         m_bQuitCommand = TRUE;
  698.         if (!m_transferstatus.socket || !m_transferstatus.socket->InitCalled())
  699.         {
  700.             Send(_T("221 Goodbye"));
  701.             if (m_pSslLayer)
  702.             {
  703.                 if (ShutDown() || WSAGetLastError() != WSAEWOULDBLOCK)
  704.                     ForceClose(5);
  705.             }
  706.             else if (CanQuit())
  707.                 ForceClose(5);
  708.         }
  709.         break;
  710.     case COMMAND_CWD:
  711.         {
  712.             //Unquote args
  713.             if (!UnquoteArgs(args))
  714.             {
  715.                 Send(_T("501 Syntax error"));
  716.                 break;
  717.             }
  718.  
  719.             if (args == _T(""))
  720.             {
  721.                 CStdString str;
  722.                 str.Format(_T("250 Broken client detected, missing argument to CWD. \"%s\" is current directory."), m_CurrentServerDir);
  723.                 Send(str);
  724.                 break;
  725.             }
  726.  
  727.             int res = m_pOwner->m_pPermissions->ChangeCurrentDir(m_status.user, m_CurrentServerDir, args);
  728.             if (!res)
  729.             {
  730.                 CStdString str;
  731.                 str.Format(_T("250 CWD successful. \"%s\" is current directory."), m_CurrentServerDir);
  732.                 Send(str);
  733.             }
  734.             else if (res & PERMISSION_DENIED)
  735.             {
  736.                 CStdString str;
  737.                 str.Format(_T("550 CWD failed. \"%s\": Permission denied."), args);
  738.                 Send(str);
  739.             }
  740.             else if (res & PERMISSION_INVALIDNAME)
  741.             {
  742.                 CStdString str;
  743.                 str.Format(_T("550 CWD failed. \"%s\": Filename invalid."), args);
  744.                 Send(str);
  745.             }
  746.             else if (res)
  747.             {
  748.                 CStdString str;
  749.                 str.Format(_T("550 CWD failed. \"%s\": directory not found."), args);
  750.                 Send(str);
  751.             }
  752.         }
  753.         break;
  754.     case COMMAND_PWD:
  755.     case COMMAND_XPWD:
  756.         {
  757.             CStdString str;
  758.             str.Format(_T("257 \"%s\" is current directory."), m_CurrentServerDir);
  759.             Send(str);
  760.         }
  761.         break;
  762.     case COMMAND_PORT:
  763.         {
  764.             if (GetFamily() != AF_INET)
  765.             {
  766.                 Send(_T("500 You are connected using IPv6. PORT is only for IPv4. You have to use the EPRT command instead."));
  767.                 break;
  768.             }
  769.  
  770.             if (m_transferstatus.socket)
  771.             {
  772.                 SendTransferinfoNotification();
  773.                 delete m_transferstatus.socket;
  774.                 m_transferstatus.socket = 0;
  775.             }
  776.             int count = 0;
  777.             int pos = 0;
  778.             //Convert commas to dots
  779.             args.Replace(_T(","), _T("."));
  780.             while (1)
  781.             {
  782.                 pos = args.Find(_T("."), pos);
  783.                 if (pos != -1)
  784.                     count++;
  785.                 else
  786.                     break;
  787.                 pos++;
  788.             }
  789.             if (count != 5)
  790.             {
  791.                 Send(_T("501 Syntax error"));
  792.                 m_transferstatus.pasv = -1;
  793.                 break;
  794.             }
  795.             CStdString ip;
  796.             int port = 0;
  797.             int i = args.ReverseFind('.');
  798.             port = _ttoi(args.Right(args.GetLength() - (i + 1))); //get ls byte of server socket
  799.             args = args.Left(i);
  800.             i = args.ReverseFind('.');
  801.             port += 256 * _ttoi(args.Right(args.GetLength() - (i + 1))); // add ms byte to server socket
  802.             ip = args.Left(i);
  803.  
  804. #ifdef _UNICODE
  805.             int res = inet_addr(ConvToLocal(ip));
  806. #else
  807.             int res = inet_addr(ip);
  808. #endif
  809.             if (res == INADDR_NONE)
  810.             {
  811.                 // Fix: Convert IP in PORT command to int and back to string (strips
  812.                 // leading zeros) because some FTP clients prepend zeros to it.
  813.                 // inet_addr() thinks this is an octal number and will return INADDR_NONE
  814.                 // if 8 or 9 are encountered.
  815.                 CStdString decIP;
  816.                 ip += _T(".");
  817.                 int pos = ip.Find('.');
  818.                 while (pos != -1)
  819.                 {
  820.                     CStdString tmp;
  821.                     tmp.Format(_T("%d."), _ttoi(ip.Left(pos)));
  822.                     decIP += tmp;
  823.  
  824.                     ip = ip.Mid(pos + 1);
  825.                     pos = ip.Find('.');
  826.                 }
  827.  
  828.                 ip = decIP.Left(decIP.GetLength() - 1);
  829. #ifdef _UNICODE
  830.                 res = inet_addr(ConvToLocal(ip));
  831. #else
  832.                 res = inet_addr(ip);
  833. #endif
  834.             }
  835.  
  836.             if (res == INADDR_NONE || port < 1 || port > 65535)
  837.              {
  838.                 Send(_T("501 Syntax error"));
  839.                 m_transferstatus.pasv = -1;
  840.                 break;
  841.             }
  842.  
  843.             if (m_pOwner->m_pOptions->GetOptionVal(OPTION_ACTIVE_IGNORELOCAL))
  844.             {
  845.                 CStdString peerAddr;
  846.                 UINT peerPort = 0;
  847.                 if (GetPeerName(peerAddr, peerPort))
  848.                 {
  849.                     if (!IsRoutableAddress(ip) && IsRoutableAddress(peerAddr))
  850.                         ip = peerAddr;
  851.                 }
  852.             }
  853.  
  854.             m_transferstatus.ip = ip;
  855.             m_transferstatus.port = port;
  856.             m_transferstatus.pasv = 0;
  857.             m_transferstatus.family = AF_INET;
  858.             Send(_T("200 Port command successful"));
  859.             break;
  860.         }
  861.     case COMMAND_PASV:
  862.     case COMMAND_PASVSMC:
  863.         {
  864.             if (GetFamily() != AF_INET)
  865.             {
  866.                 Send(_T("500 You are connected using IPv6. PASV is only for IPv4. You have to use the EPSV command instead."));
  867.                 break;
  868.             }
  869.  
  870.             if (m_transferstatus.socket)
  871.             {
  872.                 SendTransferinfoNotification();
  873.                 delete m_transferstatus.socket;
  874.             }
  875.             m_transferstatus.family = AF_INET;
  876.             m_transferstatus.socket = new CTransferSocket(this);
  877.  
  878.             unsigned int retries = 3;
  879.             unsigned int port = 0;
  880.  
  881.             CStdString pasvIP = GetPassiveIP();
  882.             if (pasvIP == _T(""))
  883.             {
  884.                 delete m_transferstatus.socket;
  885.                 m_transferstatus.socket = NULL;
  886.                 Send(_T("421 Could not create socket, no usable IP address found."));
  887.                 m_transferstatus.pasv = -1;
  888.                 break;
  889.             }
  890.  
  891.             while (retries > 0)
  892.             {
  893.                 if (m_pOwner->m_pOptions->GetOptionVal(OPTION_USECUSTOMPASVPORT))
  894.                 {
  895.                     static UINT customPort = 0;
  896.                     unsigned int minPort = (unsigned int)m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVMINPORT);
  897.                     unsigned int maxPort = (unsigned int)m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVMAXPORT);
  898.                     if (minPort > maxPort) {
  899.                         unsigned int temp = minPort;
  900.                         minPort = maxPort;
  901.                         maxPort = temp;
  902.                     }
  903.                     if (customPort < minPort || customPort > maxPort) {
  904.                         customPort = minPort;
  905.                     }
  906.                     port = customPort;
  907.  
  908.                     ++customPort;
  909.                 } else {
  910.                     port = 0;
  911.                 }
  912.                 if (m_transferstatus.socket->Create(port, SOCK_STREAM, FD_ACCEPT))
  913.                     break;
  914.                 --retries;
  915.             }
  916.             if (retries <= 0) {
  917.                 delete m_transferstatus.socket;
  918.                 m_transferstatus.socket = NULL;
  919.                 Send(_T("421 Could not create socket."));
  920.                 m_transferstatus.pasv = -1;
  921.                 break;
  922.             }
  923.  
  924.             if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
  925.                 m_transferstatus.socket->UseGSS(m_pGssLayer);
  926.  
  927.             if (m_pSslLayer && m_bProtP)
  928.                 m_transferstatus.socket->UseSSL(m_pSslLayer->GetContext());
  929.  
  930.             if (!m_transferstatus.socket->Listen())
  931.             {
  932.                 delete m_transferstatus.socket;
  933.                 m_transferstatus.socket = NULL;
  934.                 Send(_T("421 Could not create socket, listening failed."));
  935.                 m_transferstatus.pasv = -1;
  936.                 break;
  937.             }
  938.  
  939.             //Now retrieve the port
  940.             CStdString dummy;
  941.             if (m_transferstatus.socket->GetSockName(dummy, port))
  942.             {
  943.                 //Reformat the ip
  944.                 pasvIP.Replace(_T("."), _T(","));
  945.                 //Put the answer together
  946.                 CStdString str;
  947.                 if (nCommandID == COMMAND_PASVSMC)
  948.                     str.Format(_T("227 Warning: Router with P@SW bug detected. Entering Passive Mode (%s,%d,%d)"), pasvIP, port / 256, port % 256);
  949.                 else
  950.                     str.Format(_T("227 Entering Passive Mode (%s,%d,%d)"), pasvIP, port / 256, port % 256);
  951.                 Send(str);
  952.                 m_transferstatus.pasv = 1;
  953.             }
  954.             else
  955.             {
  956.                 delete m_transferstatus.socket;
  957.                 m_transferstatus.socket = NULL;
  958.                 Send(_T("421 Could not create socket, unable to query socket for used port."));
  959.                 m_transferstatus.pasv = -1;
  960.                 break;
  961.             }
  962.             
  963.             break;
  964.         }
  965.     case COMMAND_TYPE:
  966.         {
  967.             args.MakeUpper();
  968.             if (args[0] != 'I' && args[0] != 'A' && args != _T("L 8"))
  969.             {
  970.                 Send(_T("501 Unsupported type. Supported types are I, A and L 8"));
  971.                 break;
  972.             }
  973.             m_transferstatus.type = (args[0] == 'A') ? 1 : 0;
  974.             CStdString str;
  975.             str.Format(_T("200 Type set to %s"), args);
  976.             Send(str);
  977.         }
  978.         break;
  979.     case COMMAND_LIST:
  980.         if (m_transferstatus.pasv == -1)
  981.         {
  982.             Send(_T("503 Bad sequence of commands."));
  983.             break;
  984.         }
  985.         if (!m_transferstatus.pasv && (m_transferstatus.ip == _T("") || m_transferstatus.port == -1))
  986.         {
  987.             Send(_T("503 Bad sequence of commands."));
  988.             break;
  989.         }
  990.         if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  991.         {
  992.             Send(_T("521 PROT P required"));
  993.             break;
  994.         }
  995.         else
  996.         {
  997.             //Check args, currently only supported argument is the directory which will be listed.
  998.             CStdString dirToList;
  999.             args.TrimLeft(_T(" "));
  1000.             args.TrimRight(_T(" "));
  1001.             if (args != _T(""))
  1002.             {
  1003.                 BOOL bBreak = FALSE;
  1004.                 while (args[0] == '-') //No parameters supported
  1005.                 {
  1006.                     if (args.GetLength() < 2)
  1007.                     { //Dash without param
  1008.                         Send(_T("501 Syntax error"));
  1009.                         bBreak = TRUE;
  1010.                         break;
  1011.                     }
  1012.  
  1013.                     int pos = args.Find(' ');
  1014.                     CStdString params;
  1015.                     if (pos != -1)
  1016.                     {
  1017.                         params = args.Left(1);
  1018.                         params = params.Left(pos - 1);
  1019.                         args = args.Mid(pos + 1);
  1020.                         args.TrimLeft(_T(" "));
  1021.                     }
  1022.                     else
  1023.                         args = _T("");
  1024.                     while (params != _T(""))
  1025.                     {
  1026.                         //Some parameters are not support
  1027.                         if (params[0] == 'R')
  1028.                         {
  1029.                             Send(_T("504 Command not implemented for that parameter"));
  1030.                             bBreak = TRUE;
  1031.                             break;
  1032.                         }
  1033.                         //Ignore other parameters
  1034.                         params = params.Mid(1);
  1035.                     }
  1036.  
  1037.                     if (args == _T(""))
  1038.                         break;
  1039.                 }
  1040.                 if (bBreak)
  1041.                     break;
  1042.                 if (args != _T(""))
  1043.                 {
  1044.                     //Unquote args
  1045.                     if (!UnquoteArgs(args))
  1046.                     {
  1047.                         Send(_T("501 Syntax error"));
  1048.                         break;
  1049.                     }
  1050.  
  1051.                     dirToList = args;
  1052.                 }
  1053.             }
  1054.  
  1055.             t_dirlisting *pResult;
  1056.             CStdString physicalDir, logicalDir;
  1057.             int error = m_pOwner->m_pPermissions->GetDirectoryListing(m_status.user, m_CurrentServerDir, dirToList, pResult, physicalDir, logicalDir, CPermissions::AddLongListingEntry, m_useUTF8);
  1058.             if (error & PERMISSION_DENIED)
  1059.             {
  1060.                 Send(_T("550 Permission denied."));
  1061.                 ResetTransferstatus();
  1062.                 break;
  1063.             }
  1064.             else if (error & PERMISSION_INVALIDNAME)
  1065.             {
  1066.                 Send(_T("550 Filename invalid."));
  1067.                 ResetTransferstatus();
  1068.                 break;
  1069.             }
  1070.             else if (error)
  1071.             {
  1072.                 Send(_T("550 Directory not found."));
  1073.                 ResetTransferstatus();
  1074.                 break;
  1075.             }
  1076.  
  1077.             if (!m_transferstatus.pasv)
  1078.             {
  1079.                 if (m_transferstatus.socket)
  1080.                 {
  1081.                     SendTransferinfoNotification();
  1082.                     delete m_transferstatus.socket;
  1083.                 }
  1084.                 CTransferSocket *transfersocket = new CTransferSocket(this);
  1085.                 m_transferstatus.socket = transfersocket;
  1086.                 transfersocket->Init(pResult, TRANSFERMODE_LIST);
  1087.                 if (m_transferMode == mode_zlib)
  1088.                 {
  1089.                     if (!transfersocket->InitZLib(m_zlibLevel))
  1090.                     {
  1091.                         Send(_T("550 could not initialize zlib, please use MODE S instead"));
  1092.                         ResetTransferstatus();
  1093.                         break;
  1094.                     }
  1095.                 }
  1096.  
  1097.                 if (!CreateTransferSocket(transfersocket))
  1098.                     break;
  1099.  
  1100.                 SendTransferinfoNotification(TRANSFERMODE_LIST, ConvToLocal(physicalDir), ConvToLocal(logicalDir));
  1101.                 Send(_T("150 Opening data channel for directory list."));
  1102.             }
  1103.             else
  1104.             {
  1105.                 if (!m_transferstatus.socket)
  1106.                 {
  1107.                     CPermissions::DestroyDirlisting(pResult);
  1108.                     Send(_T("503 Bad sequence of commands."));
  1109.                     break;
  1110.                 }
  1111.                 m_transferstatus.socket->Init(pResult, TRANSFERMODE_LIST);
  1112.                 if (m_transferMode == mode_zlib)
  1113.                 {
  1114.                     if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  1115.                     {
  1116.                         Send(_T("550 could not initialize zlib, please use MODE S instead"));
  1117.                         ResetTransferstatus();
  1118.                         break;
  1119.                     }
  1120.                 }
  1121.  
  1122.                 SendTransferinfoNotification(TRANSFERMODE_LIST, ConvToLocal(physicalDir), ConvToLocal(logicalDir));
  1123.                 m_transferstatus.socket->PasvTransfer();
  1124.             }
  1125.         }
  1126.         break;
  1127.     case COMMAND_REST:
  1128.         {
  1129.             BOOL error = FALSE;
  1130.             for (int i = 0; i < args.GetLength(); i++)
  1131.                 if (args[i] < '0' || args[i] > '9')
  1132.                 {
  1133.                     error = TRUE;
  1134.                     break;
  1135.                 }
  1136.             if (error)
  1137.             {
  1138.                 Send(_T("501 Bad parameter. Numeric value required"));
  1139.                 break;
  1140.             }
  1141.             m_transferstatus.rest = _ttoi64(args);
  1142.             CStdString str;
  1143.             str.Format(_T("350 Rest supported. Restarting at %I64d"), m_transferstatus.rest);
  1144.             Send(str);
  1145.         }
  1146.         break;
  1147.     case COMMAND_CDUP:
  1148.     case COMMAND_XCUP:
  1149.         {
  1150.             CStdString dir = _T("..");
  1151.             int res = m_pOwner->m_pPermissions->ChangeCurrentDir(m_status.user, m_CurrentServerDir, dir);
  1152.             if (!res)
  1153.             {
  1154.                 CStdString str;
  1155.                 str.Format(_T("200 CDUP successful. \"%s\" is current directory."), m_CurrentServerDir);
  1156.                 Send(str);
  1157.             }
  1158.             else if (res & PERMISSION_DENIED)
  1159.                 Send(_T("550 CDUP failed, permission denied."));
  1160.             else if (res & PERMISSION_INVALIDNAME)
  1161.                 Send(_T("550 CDUP failed, filename invalid."));
  1162.             else if (res)
  1163.                 Send(_T("550 CDUP failed, directory not found."));
  1164.         }
  1165.         break;
  1166.     case COMMAND_RETR:
  1167.         {
  1168.             if (m_transferstatus.pasv == -1)
  1169.             {
  1170.                 Send(_T("503 Bad sequence of commands."));
  1171.                 break;
  1172.             }
  1173.             if (!m_transferstatus.pasv && (m_transferstatus.ip == _T("") || m_transferstatus.port == -1))
  1174.             {
  1175.                 Send(_T("503 Bad sequence of commands."));
  1176.                 break;
  1177.             }
  1178.             if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  1179.             {
  1180.                 Send(_T("521 PROT P required"));
  1181.                 break;
  1182.             }
  1183.             //Much more checks
  1184.  
  1185.             //Unquote args
  1186.             if (!UnquoteArgs(args))
  1187.             {
  1188.                 Send( _T("501 Syntax error") );
  1189.                 break;
  1190.             }
  1191.  
  1192.  
  1193.             CStdString physicalFile, logicalFile;
  1194.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_READ, physicalFile, logicalFile);
  1195.             if (error & PERMISSION_DENIED)
  1196.             {
  1197.                 Send(_T("550 Permission denied"));
  1198.                 ResetTransferstatus();
  1199.             }
  1200.             else if (error & PERMISSION_INVALIDNAME)
  1201.             {
  1202.                 Send(_T("550 Filename invalid."));
  1203.                 ResetTransferstatus();
  1204.             }
  1205.             else if (error)
  1206.             {
  1207.                 Send(_T("550 File not found"));
  1208.                 ResetTransferstatus();
  1209.             }
  1210.             else
  1211.             {
  1212.                 if (!m_transferstatus.pasv)
  1213.                 {
  1214.                     if (m_transferstatus.socket)
  1215.                     {
  1216.                         SendTransferinfoNotification();
  1217.                         delete m_transferstatus.socket;
  1218.                     }
  1219.                     CTransferSocket *transfersocket = new CTransferSocket(this);
  1220.                     m_transferstatus.socket = transfersocket;
  1221.                     transfersocket->Init(physicalFile, TRANSFERMODE_SEND, m_transferstatus.rest);
  1222.                     if (m_transferMode == mode_zlib)
  1223.                     {
  1224.                         if (!transfersocket->InitZLib(m_zlibLevel))
  1225.                         {
  1226.                             Send(_T("550 could not initialize zlib, please use MODE S instead"));
  1227.                             ResetTransferstatus();
  1228.                             break;
  1229.                         }
  1230.                     }
  1231.  
  1232.                     if (!CreateTransferSocket(transfersocket))
  1233.                         break;
  1234.  
  1235.                     __int64 totalSize;
  1236.                     if (!GetLength64(physicalFile, totalSize))
  1237.                         totalSize = -1;
  1238.                     SendTransferinfoNotification(TRANSFERMODE_SEND, physicalFile, logicalFile, m_transferstatus.rest, totalSize);
  1239.  
  1240.                     Send(_T("150 Opening data channel for file transfer."));
  1241.                 }
  1242.                 else
  1243.                 {
  1244.                     if (!m_transferstatus.socket)
  1245.                     {
  1246.                         Send(_T("503 Bad sequence of commands."));
  1247.                         break;
  1248.                     }
  1249.  
  1250.                     m_transferstatus.socket->Init(physicalFile, TRANSFERMODE_SEND, m_transferstatus.rest);
  1251.                     if (m_transferMode == mode_zlib)
  1252.                     {
  1253.                         if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  1254.                         {
  1255.                             Send(_T("550 could not initialize zlib, please use MODE S instead"));
  1256.                             ResetTransferstatus();
  1257.                             break;
  1258.                         }
  1259.                     }
  1260.  
  1261.                     __int64 totalSize;
  1262.                     if (!GetLength64(physicalFile, totalSize))
  1263.                         totalSize = -1;
  1264.                     SendTransferinfoNotification(TRANSFERMODE_SEND, physicalFile, logicalFile, m_transferstatus.rest, totalSize);
  1265.  
  1266.                     m_transferstatus.socket->PasvTransfer();
  1267.                 }
  1268.                 GetSystemTime(&m_LastTransferTime);
  1269.             }
  1270.             break;
  1271.         }
  1272.     case COMMAND_STOR:
  1273.         {
  1274.             if (m_transferstatus.pasv == -1)
  1275.             {
  1276.                 Send(_T("503 Bad sequence of commands."));
  1277.                 break;
  1278.             }
  1279.             if(!m_transferstatus.pasv && (m_transferstatus.ip == _T("") || m_transferstatus.port == -1))
  1280.             {
  1281.                 Send(_T("503 Bad sequence of commands."));
  1282.                 break;
  1283.             }
  1284.             if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  1285.             {
  1286.                 Send(_T("521 PROT P required"));
  1287.                 break;
  1288.             }
  1289.             //Much more checks
  1290.  
  1291.             //Unquote args
  1292.             if (!UnquoteArgs(args))
  1293.             {
  1294.                 Send( _T("501 Syntax error") );
  1295.                 break;
  1296.             }
  1297.  
  1298.             CStdString physicalFile, logicalFile;
  1299.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, m_transferstatus.rest ? FOP_APPEND : FOP_WRITE, physicalFile, logicalFile);
  1300.             if (error & PERMISSION_DENIED)
  1301.             {
  1302.                 Send(_T("550 Permission denied"));
  1303.                 ResetTransferstatus();
  1304.             }
  1305.             else if (error & PERMISSION_INVALIDNAME)
  1306.             {
  1307.                 Send(_T("550 Filename invalid."));
  1308.                 ResetTransferstatus();
  1309.             }
  1310.             else if (error)
  1311.             {
  1312.                 Send(_T("550 Filename invalid"));
  1313.                 ResetTransferstatus();
  1314.             }
  1315.             else
  1316.             {
  1317.                 if (!m_transferstatus.pasv)
  1318.                 {
  1319.                     CTransferSocket *transfersocket = new CTransferSocket(this);
  1320.                     transfersocket->Init(physicalFile, TRANSFERMODE_RECEIVE, m_transferstatus.rest);
  1321.                     m_transferstatus.socket = transfersocket;
  1322.                     if (m_transferMode == mode_zlib)
  1323.                     {
  1324.                         if (!transfersocket->InitZLib(m_zlibLevel))
  1325.                         {
  1326.                             Send(_T("550 could not initialize zlib, please use MODE S instead"));
  1327.                             ResetTransferstatus();
  1328.                             break;
  1329.                         }
  1330.                     }
  1331.  
  1332.                     if (!CreateTransferSocket(transfersocket))
  1333.                         break;
  1334.  
  1335.                     SendTransferinfoNotification(TRANSFERMODE_RECEIVE, physicalFile, logicalFile, m_transferstatus.rest);
  1336.                     Send(_T("150 Opening data channel for file transfer."));
  1337.                 }
  1338.                 else
  1339.                 {
  1340.                     if (!m_transferstatus.socket)
  1341.                     {
  1342.                         Send(_T("503 Bad sequence of commands."));
  1343.                         break;
  1344.                     }
  1345.  
  1346.                     m_transferstatus.socket->Init(physicalFile, TRANSFERMODE_RECEIVE, m_transferstatus.rest);
  1347.                     if (m_transferMode == mode_zlib)
  1348.                     {
  1349.                         if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  1350.                         {
  1351.                             Send(_T("550 could not initialize zlib, please use MODE S instead"));
  1352.                             ResetTransferstatus();
  1353.                             break;
  1354.                         }
  1355.                     }
  1356.                     SendTransferinfoNotification(TRANSFERMODE_RECEIVE, physicalFile, logicalFile, m_transferstatus.rest);
  1357.                     m_transferstatus.socket->PasvTransfer();
  1358.                 }
  1359.                 GetSystemTime(&m_LastTransferTime);
  1360.             }
  1361.         }
  1362.         break;
  1363.     case COMMAND_SIZE:
  1364.         {
  1365.             //Unquote args
  1366.             if (!UnquoteArgs(args))
  1367.             {
  1368.                 Send( _T("501 Syntax error") );
  1369.                 break;
  1370.             }
  1371.  
  1372.             CStdString physicalFile, logicalFile;
  1373.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_LIST, physicalFile, logicalFile);
  1374.             if (error & PERMISSION_DENIED)
  1375.                 Send(_T("550 Permission denied"));
  1376.             else if (error & PERMISSION_INVALIDNAME)
  1377.                 Send(_T("550 Filename invalid."));
  1378.             else if (error)
  1379.                 Send(_T("550 File not found"));
  1380.             else
  1381.             {
  1382.                 CStdString str;
  1383.                 _int64 length;
  1384.                 if (GetLength64(physicalFile, length))
  1385.                     str.Format(_T("213 %I64d"), length);
  1386.                 else
  1387.                     str = _T("550 File not found");
  1388.                 Send(str);
  1389.             }
  1390.         }
  1391.         break;
  1392.     case COMMAND_DELE:
  1393.         {
  1394.             //Unquote args
  1395.             if (!UnquoteArgs(args))
  1396.             {
  1397.                 Send(_T("501 Syntax error"));
  1398.                 break;
  1399.             }
  1400.  
  1401.             CStdString physicalFile, logicalFile;
  1402.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_DELETE, physicalFile, logicalFile);
  1403.             if (error & PERMISSION_DENIED)
  1404.                 Send(_T("550 Permission denied"));
  1405.             else if (error & PERMISSION_INVALIDNAME)
  1406.                 Send(_T("550 Filename invalid."));
  1407.             else if (error)
  1408.                 Send(_T("550 File not found"));
  1409.             else
  1410.             {
  1411.                 bool success = DeleteFile(physicalFile) == TRUE;
  1412.                 if (!success && GetLastError() == ERROR_ACCESS_DENIED)
  1413.                 {
  1414.                     DWORD attr = GetFileAttributes(physicalFile);
  1415.                     if (attr != INVALID_FILE_ATTRIBUTES && attr & FILE_ATTRIBUTE_READONLY)
  1416.                     {
  1417.                         attr &= ~FILE_ATTRIBUTE_READONLY;
  1418.                         SetFileAttributes(physicalFile, attr);
  1419.  
  1420.                         success = DeleteFile(physicalFile) == TRUE;
  1421.                     }
  1422.                 }
  1423.                 if (!success)
  1424.                     Send(_T("500 Failed to delete the file."));
  1425.                 else
  1426.                     Send(_T("250 File deleted successfully"));
  1427.             }
  1428.         }
  1429.         break;
  1430.     case COMMAND_RMD:
  1431.     case COMMAND_XRMD:
  1432.         {
  1433.             //Unquote args
  1434.             if (!UnquoteArgs(args))
  1435.             {
  1436.                 Send( _T("501 Syntax error") );
  1437.                 break;
  1438.             }
  1439.  
  1440.             CStdString physicalFile, logicalFile;
  1441.             int error = m_pOwner->m_pPermissions->CheckDirectoryPermissions(m_status.user, args, m_CurrentServerDir, DOP_DELETE, physicalFile, logicalFile);
  1442.             if (error & PERMISSION_DENIED)
  1443.                 Send(_T("550 Permission denied"));
  1444.             else if (error & PERMISSION_INVALIDNAME)
  1445.                 Send(_T("550 Filename invalid."));
  1446.             else if (error)
  1447.                 Send(_T("550 Directory not found"));
  1448.             else
  1449.             {
  1450.                 if (!RemoveDirectory(physicalFile))
  1451.                 {
  1452.                     if (GetLastError() == ERROR_DIR_NOT_EMPTY)
  1453.                         Send(_T("550 Directory not empty."));
  1454.                     else
  1455.                         Send(_T("450 Internal error deleting the directory."));
  1456.                 }
  1457.                 else
  1458.                     Send(_T("250 Directory deleted successfully"));
  1459.             }
  1460.         }
  1461.         break;
  1462.     case COMMAND_MKD:
  1463.     case COMMAND_XMKD:
  1464.         {
  1465.             //Unquote args
  1466.             if (!UnquoteArgs(args))
  1467.             {
  1468.                 Send( _T("501 Syntax error") );
  1469.                 break;
  1470.             }
  1471.  
  1472.             CStdString physicalFile, logicalFile;
  1473.             int error = m_pOwner->m_pPermissions->CheckDirectoryPermissions(m_status.user, args, m_CurrentServerDir, DOP_CREATE, physicalFile, logicalFile);
  1474.             if (error & PERMISSION_DENIED)
  1475.                 Send(_T("550 Can't create directory. Permission denied"));
  1476.             else if (error & PERMISSION_INVALIDNAME)
  1477.                 Send(_T("550 Filename invalid."));
  1478.             else if (error & PERMISSION_DOESALREADYEXIST && (error & PERMISSION_FILENOTDIR)!=PERMISSION_FILENOTDIR)
  1479.                 Send(_T("550 Directory already exists"));
  1480.             else if (error & PERMISSION_FILENOTDIR)
  1481.                 Send(_T("550 File with same name already exists"));
  1482.             else if (error)
  1483.                 Send(_T("550 Directoryname not valid"));
  1484.             else
  1485.             {
  1486.                 CStdString str;
  1487.                 BOOL res = FALSE;
  1488.                 BOOL bReplySent = FALSE;
  1489.                 physicalFile += _T("\\");
  1490.                 while (physicalFile != _T(""))
  1491.                 {
  1492.                     CStdString piece = physicalFile.Left(physicalFile.Find('\\')+1);
  1493.                     if (piece.Right(2) == _T(".\\"))
  1494.                     {
  1495.                         Send(_T("550 Directoryname not valid"));
  1496.                         bReplySent = TRUE;
  1497.                         break;
  1498.                     }
  1499.                     str += piece;
  1500.                     physicalFile = physicalFile.Mid(physicalFile.Find('\\') + 1);
  1501.                     res = CreateDirectory(str, 0);
  1502.                 }
  1503.                 if (!bReplySent)
  1504.                     if (!res)//CreateDirectory(result+"\\",0))
  1505.                     {
  1506.                         int error = GetLastError();
  1507.                         if (error == ERROR_ALREADY_EXISTS)
  1508.                             Send(_T("550 Directory already exists"));
  1509.                         else
  1510.                             Send(_T("450 Internal error creating the directory."));
  1511.                     }
  1512.                     else
  1513.                         Send(_T("257 \"") + logicalFile + _T("\" created successfully"));
  1514.             }
  1515.         }
  1516.         break;
  1517.     case COMMAND_RNFR:
  1518.         {
  1519.             //Unquote args
  1520.             if (!UnquoteArgs(args))
  1521.             {
  1522.                 Send( _T("501 Syntax error") );
  1523.                 break;
  1524.             }
  1525.  
  1526.             RenName = _T("");
  1527.  
  1528.             CStdString physicalFile, logicalFile;
  1529.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_DELETE, physicalFile, logicalFile);
  1530.             if (!error)
  1531.             {
  1532.                 RenName = physicalFile;
  1533.                 bRenFile = TRUE;
  1534.                 Send(_T("350 File exists, ready for destination name."));
  1535.                 break;
  1536.             }
  1537.             else if (error & PERMISSION_DENIED)
  1538.                 Send(_T("550 Permission denied"));
  1539.             else if (error & PERMISSION_INVALIDNAME)
  1540.                 Send(_T("550 Filename invalid."));
  1541.             else
  1542.             {
  1543.                 int error2 = m_pOwner->m_pPermissions->CheckDirectoryPermissions(m_status.user, args, m_CurrentServerDir, DOP_DELETE, physicalFile, logicalFile);
  1544.                 if (!error2)
  1545.                 {
  1546.                     RenName = physicalFile;
  1547.                     bRenFile = FALSE;
  1548.                     Send(_T("350 Directory exists, ready for destination name."));
  1549.                 }
  1550.                 else if (error2 & PERMISSION_DENIED)
  1551.                     Send(_T("550 Permission denied"));
  1552.                 else if (error2 & PERMISSION_INVALIDNAME)
  1553.                     Send(_T("550 Filename invalid."));
  1554.                 else
  1555.                     Send(_T("550 file/directory not found"));
  1556.                 break;
  1557.             }
  1558.         }
  1559.         break;
  1560.     case COMMAND_RNTO:
  1561.         {
  1562.             if (RenName == _T(""))
  1563.             {
  1564.                 Send(_T("503 Bad sequence of commands!"));
  1565.                 break;
  1566.             }
  1567.  
  1568.             //Unquote args
  1569.             if (!UnquoteArgs(args))
  1570.             {
  1571.                 Send( _T("501 Syntax error") );
  1572.                 break;
  1573.             }
  1574.  
  1575.             if (bRenFile)
  1576.             {
  1577.                 CStdString physicalFile, logicalFile;
  1578.                 int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_CREATENEW, physicalFile, logicalFile);
  1579.                 if (error)
  1580.                     RenName = _T("");
  1581.                 if (error & PERMISSION_DENIED)
  1582.                     Send(_T("550 Permission denied"));
  1583.                 else if (error & PERMISSION_INVALIDNAME)
  1584.                     Send(_T("553 Filename invalid."));
  1585.                 else if (error & PERMISSION_DOESALREADYEXIST && (error & PERMISSION_DIRNOTFILE)!=PERMISSION_DIRNOTFILE)
  1586.                     Send(_T("553 file exists"));
  1587.                 else if (error)
  1588.                     Send(_T("553 Filename invalid"));
  1589.                 else
  1590.                 {
  1591.                     if (!MoveFile(RenName, physicalFile))
  1592.                         Send(_T("450 Internal error renaming the file"));
  1593.                     else
  1594.                         Send(_T("250 file renamed successfully"));
  1595.                 }
  1596.             }
  1597.             else
  1598.             {
  1599.                 CStdString physicalFile, logicalFile;
  1600.                 int error = m_pOwner->m_pPermissions->CheckDirectoryPermissions(m_status.user, args, m_CurrentServerDir, DOP_CREATE, physicalFile, logicalFile);
  1601.                 if (error)
  1602.                     RenName = _T("");
  1603.                 if (error & PERMISSION_DENIED)
  1604.                     Send(_T("550 Permission denied"));
  1605.                 else if (error & PERMISSION_INVALIDNAME)
  1606.                     Send(_T("550 Filename invalid."));
  1607.                 else if (error & PERMISSION_DOESALREADYEXIST && (error & PERMISSION_FILENOTDIR)!=PERMISSION_FILENOTDIR)
  1608.                     Send(_T("550 file exists"));
  1609.                 else if (error)
  1610.                     Send(_T("550 Filename invalid"));
  1611.                 else
  1612.                 {
  1613.                     if (!MoveFile(RenName, physicalFile))
  1614.                         Send(_T("450 Internal error renaming the file"));
  1615.                     else
  1616.                         Send(_T("250 file renamed successfully"));
  1617.                 }
  1618.             }
  1619.         }
  1620.         break;
  1621.     case COMMAND_ABOR:
  1622.         {
  1623.             if (m_transferstatus.socket)
  1624.             {
  1625.                 if (m_transferstatus.socket->Started())
  1626.                     Send(_T("426 Connection closed; transfer aborted."));
  1627.             }
  1628.             Send(_T("226 ABOR command successful"));
  1629.             ResetTransferstatus();
  1630.         break;
  1631.         }
  1632.     case COMMAND_SYST:
  1633.         Send(_T("215 UNIX emulated by FileZilla"));
  1634.         break;
  1635.     case COMMAND_NOOP:
  1636.     case COMMAND_NOP:
  1637.         Send(_T("200 OK"));
  1638.         break;
  1639.     case COMMAND_APPE:
  1640.         {
  1641.             if (m_transferstatus.pasv == -1)
  1642.             {
  1643.                 Send(_T("503 Bad sequence of commands."));
  1644.                 break;
  1645.             }
  1646.             if (!m_transferstatus.pasv && (m_transferstatus.ip == _T("") || m_transferstatus.port == -1))
  1647.             {
  1648.                 Send(_T("503 Bad sequence of commands."));
  1649.                 break;
  1650.             }
  1651.             if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  1652.             {
  1653.                 Send(_T("521 PROT P required"));
  1654.                 break;
  1655.             }
  1656.             //Much more checks
  1657.  
  1658.             //Unquote args
  1659.             if (!UnquoteArgs(args))
  1660.             {
  1661.                 Send( _T("501 Syntax error") );
  1662.                 break;
  1663.             }
  1664.  
  1665.             CStdString physicalFile, logicalFile;
  1666.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_APPEND, physicalFile, logicalFile);
  1667.             if (error & PERMISSION_DENIED)
  1668.             {
  1669.                 Send(_T("550 Permission denied"));
  1670.                 ResetTransferstatus();
  1671.             }
  1672.             else if (error & PERMISSION_INVALIDNAME)
  1673.             {
  1674.                 Send(_T("550 Filename invalid."));
  1675.                 ResetTransferstatus();
  1676.             }
  1677.             else if (error)
  1678.             {
  1679.                 Send(_T("550 Filename invalid"));
  1680.                 ResetTransferstatus();
  1681.             }
  1682.             else
  1683.             {
  1684.                 _int64 size = 0;
  1685.                 if (!GetLength64(physicalFile, size))
  1686.                     size = 0;
  1687.  
  1688.                 m_transferstatus.rest = size;
  1689.  
  1690.                 if (!m_transferstatus.pasv)
  1691.                 {
  1692.                     CTransferSocket *transfersocket = new CTransferSocket(this);
  1693.                     transfersocket->Init(physicalFile, TRANSFERMODE_RECEIVE, m_transferstatus.rest);
  1694.                     m_transferstatus.socket = transfersocket;
  1695.                     if (m_transferMode == mode_zlib)
  1696.                     {
  1697.                         if (!transfersocket->InitZLib(m_zlibLevel))
  1698.                         {
  1699.                             Send(_T("550 could not initialize zlib, please use MODE S instead"));
  1700.                             ResetTransferstatus();
  1701.                             break;
  1702.                         }
  1703.                     }
  1704.  
  1705.                     if (!CreateTransferSocket(transfersocket))
  1706.                         break;
  1707.  
  1708.                     SendTransferinfoNotification(TRANSFERMODE_RECEIVE, physicalFile, logicalFile, m_transferstatus.rest);
  1709.  
  1710.                     CStdString str;
  1711.                     str.Format(_T("150 Opening data channel for file transfer, restarting at offset %I64d"), size);
  1712.                     Send(str);
  1713.                 }
  1714.                 else
  1715.                 {
  1716.                     if (!m_transferstatus.socket)
  1717.                     {
  1718.                         Send(_T("503 Bad sequence of commands."));
  1719.                         break;
  1720.                     }
  1721.                     m_transferstatus.socket->Init(physicalFile, TRANSFERMODE_RECEIVE, m_transferstatus.rest);
  1722.                     if (m_transferMode == mode_zlib)
  1723.                     {
  1724.                         if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  1725.                         {
  1726.                             Send(_T("550 could not initialize zlib, please use MODE S instead"));
  1727.                             ResetTransferstatus();
  1728.                             break;
  1729.                         }
  1730.                     }
  1731.                     SendTransferinfoNotification(TRANSFERMODE_RECEIVE, physicalFile, logicalFile, m_transferstatus.rest);
  1732.                     m_transferstatus.socket->PasvTransfer();
  1733.                 }
  1734.                 GetSystemTime(&m_LastTransferTime);
  1735.             }
  1736.         }
  1737.         break;
  1738.     case COMMAND_NLST:
  1739.         if (m_transferstatus.pasv == -1)
  1740.         {
  1741.             Send(_T("503 Bad sequence of commands."));
  1742.             break;
  1743.         }
  1744.         if (!m_transferstatus.pasv && (m_transferstatus.ip == _T("") || m_transferstatus.port == -1))
  1745.         {
  1746.             Send(_T("503 Bad sequence of commands."));
  1747.             break;
  1748.         }
  1749.         if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  1750.         {
  1751.             Send(_T("521 PROT P required"));
  1752.             break;
  1753.         }
  1754.         //Much more checks
  1755.         else
  1756.         {
  1757.             //Check args, currently only supported argument is the directory which will be listed.
  1758.             if (args != _T(""))
  1759.             {
  1760.                 BOOL bBreak = FALSE;
  1761.                 while (args[0] == '-') //No parameters supported
  1762.                 {
  1763.                     if (args.GetLength() < 2)
  1764.                     { //Dash without param
  1765.                         Send(_T("501 Syntax error"));
  1766.                         bBreak = TRUE;
  1767.                         break;
  1768.                     }
  1769.  
  1770.                     int pos = args.Find(' ');
  1771.                     CStdString params;
  1772.                     if (pos != -1)
  1773.                     {
  1774.                         params = args.Left(1);
  1775.                         params = params.Left(pos-1);
  1776.                         args = args.Mid(pos+1);
  1777.                         args.TrimLeft(_T(" "));
  1778.                     }
  1779.                     else
  1780.                         args = _T("");
  1781.                     while (params != _T(""))
  1782.                     {
  1783.                         //Some parameters are not support
  1784.                         if (params[0] == 'R')
  1785.                         {
  1786.                             Send(_T("504 Command not implemented for that parameter"));
  1787.                             bBreak = TRUE;
  1788.                             break;
  1789.                         }
  1790.                         //Ignore other parameters
  1791.                         params = params.Mid(1);
  1792.                     }
  1793.  
  1794.                     if (args == _T(""))
  1795.                         break;
  1796.                 }
  1797.                 if (bBreak)
  1798.                     break;
  1799.                 if (args != _T(""))
  1800.                 {
  1801.                     //Unquote args
  1802.                     if (!UnquoteArgs(args))
  1803.                     {
  1804.                         Send( _T("501 Syntax error") );
  1805.                         break;
  1806.                     }
  1807.                 }
  1808.             }
  1809.  
  1810.             t_dirlisting *pResult;
  1811.             CStdString physicalDir, logicalDir;
  1812.             int error = m_pOwner->m_pPermissions->GetDirectoryListing(m_status.user, m_CurrentServerDir, args, pResult, physicalDir, logicalDir, CPermissions::AddShortListingEntry, m_useUTF8);
  1813.             if (error & PERMISSION_DENIED)
  1814.             {
  1815.                 Send(_T("550 Permission denied"));
  1816.                 ResetTransferstatus();
  1817.             }
  1818.             else if (error & PERMISSION_INVALIDNAME)
  1819.             {
  1820.                 Send(_T("550 Filename invalid."));
  1821.                 ResetTransferstatus();
  1822.             }
  1823.             else if (error)
  1824.             {
  1825.                 Send(_T("550 Directory not found"));
  1826.                 ResetTransferstatus();
  1827.             }
  1828.             else
  1829.             {
  1830.                 if (!m_transferstatus.pasv)
  1831.                 {
  1832.                     CTransferSocket *transfersocket = new CTransferSocket(this);
  1833.                     m_transferstatus.socket = transfersocket;
  1834.                     transfersocket->Init(pResult, TRANSFERMODE_NLST);
  1835.                     if (m_transferMode == mode_zlib)
  1836.                     {
  1837.                         if (!transfersocket->InitZLib(m_zlibLevel))
  1838.                         {
  1839.                             Send(_T("550 could not initialize zlib, please use MODE S instead"));
  1840.                             ResetTransferstatus();
  1841.                             break;
  1842.                         }
  1843.                     }
  1844.  
  1845.                     if (!CreateTransferSocket(transfersocket))
  1846.                         break;
  1847.  
  1848.                     SendTransferinfoNotification(TRANSFERMODE_LIST, physicalDir, logicalDir); // Use TRANSFERMODE_LIST instead of TRANSFERMODE_NLST.
  1849.                     Send(_T("150 Opening data channel for directory list."));
  1850.                 }
  1851.                 else
  1852.                 {
  1853.                     if (!m_transferstatus.socket)
  1854.                     {
  1855.                         CPermissions::DestroyDirlisting(pResult);
  1856.                         Send(_T("503 Bad sequence of commands."));
  1857.                         break;
  1858.                     }
  1859.                     m_transferstatus.socket->Init(pResult, TRANSFERMODE_NLST );
  1860.                     if (m_transferMode == mode_zlib)
  1861.                     {
  1862.                         if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  1863.                         {
  1864.                             Send(_T("550 could not initialize zlib, please use MODE S instead"));
  1865.                             ResetTransferstatus();
  1866.                             break;
  1867.                         }
  1868.                     }
  1869.                     SendTransferinfoNotification(TRANSFERMODE_LIST, physicalDir, logicalDir); // Use TRANSFERMODE_LIST instead of TRANSFERMODE_NLST.
  1870.                     m_transferstatus.socket->PasvTransfer();
  1871.                 }
  1872.             }
  1873.         }
  1874.         break;
  1875.     case COMMAND_MDTM:
  1876.         {
  1877.             //Unquote args
  1878.             if (!UnquoteArgs(args))
  1879.             {
  1880.                 Send( _T("501 Syntax error") );
  1881.                 break;
  1882.             }
  1883.  
  1884.             CStdString physicalFile, logicalFile;
  1885.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_LIST, physicalFile, logicalFile);
  1886.             if (error & PERMISSION_DENIED)
  1887.                 Send(_T("550 Permission denied"));
  1888.             else if (error & PERMISSION_INVALIDNAME)
  1889.                 Send(_T("550 Filename invalid."));
  1890.             else if (error & 2)
  1891.                 Send(_T("550 File not found"));
  1892.             else
  1893.             {
  1894.                 CFileStatus64 status;
  1895.                 GetStatus64(physicalFile, status);
  1896.                 CStdString str;
  1897.                 SYSTEMTIME time;
  1898.                 FileTimeToSystemTime(&status.m_mtime, &time);
  1899.                 str.Format(_T("213 %04d%02d%02d%02d%02d%02d"),
  1900.                             time.wYear,
  1901.                             time.wMonth,
  1902.                             time.wDay,
  1903.                             time.wHour,
  1904.                             time.wMinute,
  1905.                             time.wSecond);
  1906.                 Send(str);
  1907.             }
  1908.         }
  1909.         break;
  1910.     case COMMAND_EPSV:
  1911.         {
  1912.             if (m_transferstatus.socket)
  1913.             {
  1914.                 SendTransferinfoNotification();
  1915.                 delete m_transferstatus.socket;
  1916.             }
  1917.             m_transferstatus.family = (GetFamily() == AF_INET) ? 1 : 2;
  1918.             m_transferstatus.socket = new CTransferSocket(this);
  1919.  
  1920.             unsigned int port = 0;
  1921.             unsigned int retries = 3;
  1922.             while (retries > 0) {
  1923.                 if (m_pOwner->m_pOptions->GetOptionVal(OPTION_USECUSTOMPASVPORT)) {
  1924.                     static UINT customPort = 0;
  1925.                     unsigned int minPort = (unsigned int)m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVMINPORT);
  1926.                     unsigned int maxPort = (unsigned int)m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVMAXPORT);
  1927.                     if (minPort > maxPort) {
  1928.                         unsigned int temp = minPort;
  1929.                         minPort = maxPort;
  1930.                         maxPort = temp;
  1931.                     }
  1932.                     if (customPort < minPort || customPort > maxPort) {
  1933.                         customPort = minPort;
  1934.                     }
  1935.                     port = customPort;
  1936.                     ++customPort;
  1937.                 }
  1938.                 if (m_transferstatus.socket->Create(port, SOCK_STREAM, FD_ACCEPT, 0, GetFamily()))
  1939.                 {
  1940.                     break;
  1941.                 }
  1942.                 --retries;
  1943.             }
  1944.             if (retries <= 0) {
  1945.                 delete m_transferstatus.socket;
  1946.                 m_transferstatus.socket=0;
  1947.                 Send(_T("421 Could not create socket."));
  1948.                 break;
  1949.             }
  1950.  
  1951.             if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
  1952.                 m_transferstatus.socket->UseGSS(m_pGssLayer);
  1953.  
  1954.             if (m_pSslLayer && m_bProtP)
  1955.                 m_transferstatus.socket->UseSSL(m_pSslLayer->GetContext());
  1956.  
  1957.             if (!m_transferstatus.socket->Listen())
  1958.             {
  1959.                 delete m_transferstatus.socket;
  1960.                 m_transferstatus.socket=0;
  1961.                 Send(_T("421 Could not create socket, listening failed."));
  1962.                 m_transferstatus.pasv = -1;
  1963.                 break;
  1964.             }
  1965.  
  1966.             //Now retrieve the port
  1967.             CStdString dummy;
  1968.             if (m_transferstatus.socket->GetSockName(dummy, port))
  1969.             {
  1970.                 //Put the answer together
  1971.                 CStdString str;
  1972.                 str.Format(_T("229 Entering Extended Passive Mode (|||%d|)"), port);
  1973.                 Send(str);
  1974.                 m_transferstatus.pasv=1;
  1975.             }
  1976.             else
  1977.             {
  1978.                 delete m_transferstatus.socket;
  1979.                 m_transferstatus.socket=0;
  1980.                 Send(_T("421 Could not create socket, unable to query socket for used port."));
  1981.                 m_transferstatus.pasv = -1;
  1982.             }
  1983.             break;
  1984.         }
  1985.     case COMMAND_EPRT:
  1986.         {
  1987.             if (m_transferstatus.socket)
  1988.             {
  1989.                 SendTransferinfoNotification();
  1990.                 delete m_transferstatus.socket;
  1991.                 m_transferstatus.socket=0;
  1992.             }
  1993.  
  1994.             if (args[0] != '|')
  1995.             {
  1996.                 Send(_T("501 Syntax error"));
  1997.                 m_transferstatus.pasv = -1;
  1998.                 break;
  1999.             }
  2000.             args = args.Mid(1);
  2001.  
  2002.             int pos = args.Find('|');
  2003.             if (pos < 1 || (pos>=(args.GetLength()-1)))
  2004.             {
  2005.                 Send(_T("501 Syntax error"));
  2006.                 m_transferstatus.pasv = -1;
  2007.                 break;
  2008.             }
  2009.             int protocol = _ttoi(args.Left(pos));
  2010.  
  2011.             bool ipv6Allowed = m_pOwner->m_pOptions->GetOptionVal(OPTION_DISABLE_IPV6) == 0;
  2012.             if (protocol != 1 && (protocol != 2 || !ipv6Allowed))
  2013.             {
  2014.                 if (ipv6Allowed)
  2015.                     Send(_T("522 Extended Port Failure - unknown network protocol. Supported protocols: (1,2)"));
  2016.                 else
  2017.                     Send(_T("522 Extended Port Failure - unknown network protocol. Supported protocols: (1)"));
  2018.                 m_transferstatus.pasv = -1;
  2019.                 break;
  2020.             }
  2021.             args = args.Mid(pos + 1);
  2022.  
  2023.             pos = args.Find('|');
  2024.             if (pos < 1 || (pos>=(args.GetLength()-1)))
  2025.             {
  2026.                 Send(_T("501 Syntax error"));
  2027.                 m_transferstatus.pasv = -1;
  2028.                 break;
  2029.             }
  2030.             CStdString ip = args.Left(pos);
  2031.             if (protocol == 1)
  2032.             {
  2033. #ifdef _UNICODE
  2034.                 if (inet_addr(ConvToLocal(ip)) == INADDR_NONE)
  2035. #else
  2036.                 if (inet_addr(ip) == INADDR_NONE)
  2037. #endif
  2038.                 {
  2039.                     Send(_T("501 Syntax error, not a valid IPv4 address"));
  2040.                     m_transferstatus.pasv = -1;
  2041.                     break;
  2042.                 }
  2043.             }
  2044.             else
  2045.             {
  2046.                 ip = GetIPV6LongForm(ip);
  2047.                 if (ip.IsEmpty())
  2048.                 {
  2049.                     Send(_T("501 Syntax error, not a valid IPv6 address"));
  2050.                     m_transferstatus.pasv = -1;
  2051.                     break;
  2052.                 }
  2053.             }
  2054.             args = args.Mid(pos + 1);
  2055.  
  2056.             pos = args.Find('|');
  2057.             if (pos < 1)
  2058.             {
  2059.                 Send(_T("501 Syntax error"));
  2060.                 m_transferstatus.pasv = -1;
  2061.                 break;
  2062.             }
  2063.             int port = _ttoi(args.Left(pos));
  2064.             if (port < 1 || port > 65535)
  2065.             {
  2066.                 Send(_T("501 Syntax error"));
  2067.                 m_transferstatus.pasv = -1;
  2068.                 break;
  2069.             }
  2070.  
  2071.             m_transferstatus.port = port;
  2072.             m_transferstatus.ip = ip;
  2073.             m_transferstatus.family = (protocol == 1) ? AF_INET : AF_INET6;
  2074.  
  2075.             m_transferstatus.pasv = 0;
  2076.             Send(_T("200 Port command successful"));
  2077.             break;
  2078.         }
  2079.     case COMMAND_AUTH:
  2080.         {
  2081.             if (m_nRecvBufferPos || m_RecvLineBuffer.size() ) {
  2082.                 Send(_T("503 Bad sequence of commands. Received additional data after the AUTH command before this reply could be sent."));
  2083.                 ForceClose(-1);
  2084.                 break;
  2085.             }
  2086.  
  2087.             if (m_pGssLayer)
  2088.             {
  2089.                 Send(_T("534 Authentication type already set to GSSAPI"));
  2090.                 break;
  2091.             }
  2092.             else if (m_pSslLayer)
  2093.             {
  2094.                 Send(_T("534 Authentication type already set to SSL"));
  2095.                 break;
  2096.             }
  2097.             args.MakeUpper();
  2098.  
  2099.             if (args == _T("GSSAPI"))
  2100.             {
  2101.                 if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_USEGSS))
  2102.                 {
  2103.                     Send(_T("502 GSSAPI authentication not implemented"));
  2104.                     break;
  2105.                 }
  2106.  
  2107.                 m_pGssLayer = new CAsyncGssSocketLayer;
  2108.                 BOOL res = AddLayer(m_pGssLayer);
  2109.                 if (res)
  2110.                 {
  2111.                     res = m_pGssLayer->InitGSS(FALSE, (BOOL)m_pOwner->m_pOptions->GetOptionVal(OPTION_GSSPROMPTPASSWORD));
  2112.                     if (!res)
  2113.                         SendStatus(_T("Unable to init GSS"), 1);
  2114.                 }
  2115.                 if (!res)
  2116.                 {
  2117.                     RemoveAllLayers();
  2118.                     delete m_pGssLayer;
  2119.                     m_pGssLayer = NULL;
  2120.                     Send(_T("431 Could not initialize GSSAPI libraries"));
  2121.                     break;
  2122.                 }
  2123.  
  2124.                 Send(_T("334 Using authentication type GSSAPI; ADAT must follow"));
  2125.             }
  2126.             else if (args == _T("SSL") || args == _T("TLS"))
  2127.             {
  2128.                 if (m_pSslLayer)
  2129.                 {
  2130.                     Send(_T("503 Already using SSL/TLS"));
  2131.                     break;
  2132.                 }
  2133.  
  2134.                 if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_ENABLESSL) || !m_pOwner->m_pOptions->GetOptionVal(OPTION_ALLOWEXPLICITSSL))
  2135.                 {
  2136.                     Send(_T("502 SSL/TLS authentication not allowed"));
  2137.                     break;
  2138.                 }
  2139.  
  2140.                 m_pSslLayer = new CAsyncSslSocketLayer;
  2141.                 BOOL res = AddLayer(m_pSslLayer);
  2142.  
  2143.                 if (res)
  2144.                 {
  2145.                     CString error;
  2146. #ifdef _UNICODE
  2147.                     int res = m_pSslLayer->SetCertKeyFile(ConvToLocal(m_pOwner->m_pOptions->GetOption(OPTION_SSLCERTFILE)), ConvToLocal(m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYFILE)), ConvToLocal(m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYPASS)), &error);
  2148. #else
  2149.                     int res = m_pSslLayer->SetCertKeyFile(m_pOwner->m_pOptions->GetOption(OPTION_SSLCERTFILE), m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYFILE), m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYPASS), &error);
  2150. #endif
  2151.                     if (res == SSL_FAILURE_LOADDLLS)
  2152.                         SendStatus(_T("Failed to load SSL libraries"), 1);
  2153.                     else if (res == SSL_FAILURE_INITSSL)
  2154.                         SendStatus(_T("Failed to initialize SSL libraries"), 1);
  2155.                     else if (res == SSL_FAILURE_VERIFYCERT)
  2156.                     {
  2157.                         if (error != _T(""))
  2158.                             SendStatus(error, 1);
  2159.                         else
  2160.                             SendStatus(_T("Failed to set certificate and private key"), 1);
  2161.                     }
  2162.                     if (res)
  2163.                     {
  2164.                         RemoveAllLayers();
  2165.                         delete m_pSslLayer;
  2166.                         m_pSslLayer = NULL;
  2167.                         Send(_T("431 Could not initialize SSL connection"));
  2168.                         break;
  2169.                     }
  2170.                 }
  2171.  
  2172.                 if (res)
  2173.                 {
  2174.                     int code = m_pSslLayer->InitSSLConnection(false);
  2175.                     if (code == SSL_FAILURE_LOADDLLS)
  2176.                         SendStatus(_T("Failed to load SSL libraries"), 1);
  2177.                     else if (code == SSL_FAILURE_INITSSL)
  2178.                         SendStatus(_T("Failed to initialize SSL library"), 1);
  2179.  
  2180.                     res = (code == 0);
  2181.                 }
  2182.  
  2183.                 if (res)
  2184.                 {
  2185.                     if (args == _T("SSL"))
  2186.                     {
  2187.                         SendStatus(_T("234 Using authentication type SSL"), 3);
  2188.                         static const char* reply = "234 Using authentication type SSL\r\n";
  2189.                         const int len = strlen(reply);
  2190.                         res = (m_pSslLayer->SendRaw(reply, len) == len);
  2191.                     }
  2192.                     else // TLS
  2193.                     {
  2194.                         SendStatus(_T("234 Using authentication type TLS"), 3);
  2195.                         static const char* reply = "234 Using authentication type TLS\r\n";
  2196.                         const int len = strlen(reply);
  2197.                         res = (m_pSslLayer->SendRaw(reply, len) == len);
  2198.                     }
  2199.                 }
  2200.  
  2201.                 if (!res)
  2202.                 {
  2203.                     RemoveAllLayers();
  2204.                     delete m_pSslLayer;
  2205.                     m_pSslLayer = NULL;
  2206.                     Send(_T("431 Could not initialize SSL connection"));
  2207.                     break;
  2208.                 }
  2209.             }
  2210.             else
  2211.             {
  2212.                 Send(_T("504 Auth type not supported"));
  2213.                 break;
  2214.             }
  2215.  
  2216.             break;
  2217.         }
  2218.     case COMMAND_ADAT:
  2219.         if (m_pGssLayer)
  2220.         {
  2221.             char sendme[4096];
  2222. #ifdef _UNICODE
  2223.             m_pGssLayer->ProcessCommand("ADAT", ConvToLocal(args), sendme);
  2224.             Send(ConvFromLocal(sendme));
  2225. #else
  2226.             m_pGssLayer->ProcessCommand("ADAT", args, sendme);
  2227.             Send(sendme);
  2228. #endif
  2229.             
  2230.         }
  2231.         else
  2232.             Send(_T("502 Command not implemented for this authentication type"));
  2233.         break;
  2234.     case COMMAND_PBSZ:
  2235.         if (m_pGssLayer)
  2236.         {
  2237.             char sendme[4096];
  2238. #ifdef _UNICODE
  2239.             m_pGssLayer->ProcessCommand("PBSZ", ConvToLocal(args), sendme);
  2240.             Send(ConvFromLocal(sendme));
  2241. #else
  2242.             m_pGssLayer->ProcessCommand("PBSZ", args, sendme);
  2243.             Send(sendme);
  2244. #endif
  2245.         }
  2246.         else if (m_pSslLayer)
  2247.             Send(_T("200 PBSZ=0"));
  2248.         else
  2249.             Send(_T("502 Command not implemented for this authentication type"));
  2250.         break;
  2251.     case COMMAND_PROT:
  2252.         if (m_pGssLayer)
  2253.         {
  2254.             char sendme[4096];
  2255.  
  2256. #ifdef _UNICODE
  2257.             m_pGssLayer->ProcessCommand("PROT", ConvToLocal(args), sendme);
  2258.             Send(ConvFromLocal(sendme));
  2259. #else
  2260.             m_pGssLayer->ProcessCommand("PROT", args, sendme);
  2261.             Send(sendme);
  2262. #endif
  2263.         }
  2264.         else if (m_pSslLayer)
  2265.         {
  2266.             args.MakeUpper();
  2267.             if (args == _T("C"))
  2268.             {
  2269.                 if (m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP))
  2270.                     Send(_T("534 This server requires an encrypted data connection with PROT P"));
  2271.                 else
  2272.                 {
  2273.                     if (m_transferstatus.socket)
  2274.                         m_transferstatus.socket->UseSSL(0);
  2275.  
  2276.                     Send(_T("200 Protection level set to C"));
  2277.                     m_bProtP = false;
  2278.                 }
  2279.             }
  2280.             else if (args == _T("P"))
  2281.             {
  2282.                 if (m_transferstatus.socket)
  2283.                     m_transferstatus.socket->UseSSL(m_pSslLayer->GetContext());
  2284.  
  2285.                 Send(_T("200 Protection level set to P"));
  2286.                 m_bProtP = true;
  2287.             }
  2288.             else if (args == _T("S") || args == _T("E"))
  2289.                 Send(_T("504 Protection level ") + args + _T(" not supported"));
  2290.             else
  2291.                 Send(_T("504 Protection level ") + args + _T(" not recognized"));
  2292.         }
  2293.         else
  2294.             Send(_T("502 Command not implemented for this authentication type"));
  2295.         break;
  2296.     case COMMAND_FEAT:
  2297.         {
  2298.         if (!Send(_T("211-Features:")))
  2299.             break;
  2300.         if (!Send(_T(" MDTM")))
  2301.             break;
  2302.         if (!Send(_T(" REST STREAM")))
  2303.             break;
  2304.         if (!Send(_T(" SIZE")))
  2305.             break;
  2306.         if (m_pOwner->m_pOptions->GetOptionVal(OPTION_MODEZ_USE))
  2307.         {
  2308.             if (!Send(_T(" MODE Z")))
  2309.                 break;
  2310.         }
  2311.         if (!Send(_T(" MLST type*;size*;modify*;")))
  2312.             break;
  2313.         if (!Send(_T(" MLSD")))
  2314.             break;
  2315.         if (m_pOwner->m_pOptions->GetOptionVal(OPTION_ENABLESSL) && (m_pOwner->m_pOptions->GetOptionVal(OPTION_ALLOWEXPLICITSSL) || m_pSslLayer))
  2316.         {
  2317.             if (!Send(_T(" AUTH SSL")))
  2318.                 break;
  2319.             if (!Send(_T(" AUTH TLS")))
  2320.                 break;
  2321.             if (!Send(_T(" PROT")))
  2322.                 break;
  2323.             if (!Send(_T(" PBSZ")))
  2324.                 break;
  2325.         }
  2326.         if (!Send(_T(" UTF8")))
  2327.             break;
  2328.         if (!Send(_T(" CLNT")))
  2329.             break;
  2330.         if (!Send(_T(" MFMT")))
  2331.             break;
  2332.         if (m_pOwner->m_pOptions->GetOptionVal(OPTION_ENABLE_HASH))
  2333.         {
  2334.             CStdString hash = _T(" HASH ");
  2335.             hash += _T("SHA-1");
  2336.             if (m_hash_algorithm == CHashThread::SHA1)
  2337.                 hash += _T("*");
  2338.             hash += _T(";SHA-512");
  2339.             if (m_hash_algorithm == CHashThread::SHA512)
  2340.                 hash += _T("*");
  2341.             hash += _T(";MD5");
  2342.             if (m_hash_algorithm == CHashThread::MD5)
  2343.                 hash += _T("*");
  2344.             if (!Send(hash))
  2345.                 break;
  2346.         }
  2347.         if (!Send(_T("211 End")))
  2348.             break;
  2349.         break;
  2350.         }
  2351.     case COMMAND_MODE:
  2352.         if (args == _T("S") || args == _T("s"))
  2353.         {
  2354.             m_transferMode = mode_stream;
  2355.             Send(_T("200 MODE set to S."));
  2356.         }
  2357.         else if (args == _T("Z") || args == _T("z"))
  2358.         {
  2359.             if (m_pOwner->m_pOptions->GetOptionVal(OPTION_MODEZ_USE) || m_transferMode == mode_zlib)
  2360.             {
  2361.                 if (m_transferMode == mode_zlib || CheckIpForZlib())
  2362.                 {
  2363.                     m_transferMode = mode_zlib;
  2364.                     Send(_T("200 MODE set to Z."));
  2365.                 }
  2366.                 else
  2367.                     Send(_T("504 MODE Z not allowed from your IP"));
  2368.             }
  2369.             else
  2370.                 Send(_T("504 MODE Z not enabled"));
  2371.         }
  2372.         else if (args == _T("C") || args == _T("c") || args == _T("B") || args == _T("b"))
  2373.             Send(_T("502 Unimplemented MODE type"));
  2374.         else
  2375.             Send(_T("504 Unknown MODE type"));
  2376.         break;
  2377.     case COMMAND_OPTS:
  2378.         args.MakeUpper();
  2379.         if (args.Left(13) == _T("MODE Z LEVEL "))
  2380.         {
  2381.             int level = _ttoi(args.Mid(13));
  2382.             if (m_zlibLevel == level || (level >= m_pOwner->m_pOptions->GetOptionVal(OPTION_MODEZ_LEVELMIN) && level <= m_pOwner->m_pOptions->GetOptionVal(OPTION_MODEZ_LEVELMAX)))
  2383.             {
  2384.                 m_zlibLevel = level;
  2385.                 CString str;
  2386.                 str.Format(_T("200 MODE Z LEVEL set to %d"), level);
  2387.                 Send(str);
  2388.             }
  2389.             else
  2390.                 Send(_T("501 can't change MODE Z LEVEL do desired value"));
  2391.         }
  2392.         else if (args == _T("UTF8 ON"))
  2393.         {
  2394.             m_useUTF8 = true;
  2395.             Send(_T("200 UTF8 mode enabled"));
  2396.         }
  2397.         else if (args == _T("UTF8 OFF"))
  2398.         {
  2399.             m_useUTF8 = false;
  2400.             Send(_T("200 UTF8 mode disabled"));
  2401.         }
  2402.         else if (args.Left(4) == _T("MLST"))
  2403.             ParseMlstOpts(args.Mid(4));
  2404.         else if (args.Left(4) == _T("HASH"))
  2405.             ParseHashOpts(args.Mid(4));
  2406.         else
  2407.             Send(_T("501 Option not understood"));
  2408.         break;
  2409.     case COMMAND_HELP:
  2410.         if (args == _T(""))
  2411.         {
  2412.             Send(_T("214-The following commands are recognized:"));
  2413.             CString str;
  2414.             for (int i = 0; i < (sizeof(commands)/sizeof(t_command)); i++)
  2415.             {
  2416.                 CString cmd = commands[i].command;
  2417.                 while (cmd.GetLength() < 4)
  2418.                     cmd += _T(" ");
  2419.                 str += _T("   ") + cmd;
  2420.                 if (!((i + 1) % 8))
  2421.                 {
  2422.                     Send(str);
  2423.                     str = _T("");
  2424.                 }
  2425.             }
  2426.             if (str != _T(""))
  2427.                 Send(str);
  2428.             Send(_T("214 Have a nice day."));
  2429.         }
  2430.         else
  2431.         {
  2432.             args.MakeUpper();
  2433.  
  2434.             int i;
  2435.             for (i = 0; i < (sizeof(commands)/sizeof(t_command)); i++)
  2436.             {
  2437.                 if (args == commands[i].command)
  2438.                 {
  2439.                     CStdString str;
  2440.                     str.Format(_T("214 Command %s is supported by FileZilla Server"), args);
  2441.                     Send(str);
  2442.                     break;
  2443.                 }
  2444.             }
  2445.             if (i == (sizeof(commands)/sizeof(t_command)))
  2446.             {
  2447.                 CStdString str;
  2448.                 str.Format(_T("502 Command %s is not recognized or supported by FileZilla Server"), args);
  2449.                 Send(str);
  2450.             }
  2451.         }
  2452.         break;
  2453.     case COMMAND_ALLO:
  2454.         Send(_T("202 No storage allocation neccessary."));
  2455.         break;
  2456.     case COMMAND_MLST:
  2457.         {
  2458.             CStdString fact;
  2459.             CStdString logicalName;
  2460.             int res = m_pOwner->m_pPermissions->GetFact(m_status.user, m_CurrentServerDir, args, fact, logicalName, m_facts);
  2461.             if (res & PERMISSION_DENIED)
  2462.             {
  2463.                 Send(_T("550 Permission denied."));
  2464.                 break;
  2465.             }
  2466.             else if (res & PERMISSION_INVALIDNAME)
  2467.             {
  2468.                 Send(_T("550 Filename invalid."));
  2469.                 break;
  2470.             }
  2471.             else if (res)
  2472.             {
  2473.                 Send(_T("550 File or directory not found."));
  2474.                 break;
  2475.             }
  2476.             CStdString str;
  2477.             str.Format(_T("250-Listing %s"), logicalName);
  2478.             if (!Send(str))
  2479.                 break;
  2480.             fact = _T(" ") + fact;
  2481.             if (!Send(fact))
  2482.                 break;
  2483.  
  2484.             Send(_T("250 End"));
  2485.         }
  2486.         break;
  2487.     case COMMAND_MLSD:
  2488.         if (m_transferstatus.pasv == -1)
  2489.         {
  2490.             Send(_T("503 Bad sequence of commands."));
  2491.             break;
  2492.         }
  2493.         if (!m_transferstatus.pasv && (m_transferstatus.ip == _T("") || m_transferstatus.port == -1))
  2494.             Send(_T("503 Bad sequence of commands."));
  2495.         //Much more checks
  2496.         else
  2497.         {
  2498.             if (m_pSslLayer && m_pOwner->m_pOptions->GetOptionVal(OPTION_FORCEPROTP) && !m_bProtP)
  2499.             {
  2500.                 Send(_T("521 PROT P required"));
  2501.                 break;
  2502.             }
  2503.             if (args != _T(""))
  2504.             {
  2505.                 //Unquote args
  2506.                 if (!UnquoteArgs(args))
  2507.                 {
  2508.                     Send(_T("501 Syntax error"));
  2509.                     break;
  2510.                 }
  2511.             }
  2512.  
  2513.             t_dirlisting *pResult;
  2514.             CStdString physicalDir, logicalDir;
  2515.             int error = m_pOwner->m_pPermissions->GetDirectoryListing(m_status.user, m_CurrentServerDir, args, pResult, physicalDir, logicalDir, CPermissions::AddFactsListingEntry, m_useUTF8, m_facts);
  2516.             if (error & PERMISSION_DENIED)
  2517.             {
  2518.                 Send(_T("550 Permission denied"));
  2519.                 ResetTransferstatus();
  2520.             }
  2521.             else if (error & PERMISSION_INVALIDNAME)
  2522.             {
  2523.                 Send(_T("550 Filename invalid."));
  2524.                 ResetTransferstatus();
  2525.             }
  2526.             else if (error)
  2527.             {
  2528.                 Send(_T("550 Directory not found"));
  2529.                 ResetTransferstatus();
  2530.             }
  2531.             else
  2532.             {
  2533.                 if (!m_transferstatus.pasv)
  2534.                 {
  2535.                     if (m_transferstatus.socket)
  2536.                     {
  2537.                         SendTransferinfoNotification();
  2538.                         delete m_transferstatus.socket;
  2539.                     }
  2540.                     CTransferSocket *transfersocket = new CTransferSocket(this);
  2541.                     m_transferstatus.socket = transfersocket;
  2542.                     transfersocket->Init(pResult, TRANSFERMODE_LIST);
  2543.                     if (m_transferMode == mode_zlib)
  2544.                     {
  2545.                         if (!transfersocket->InitZLib(m_zlibLevel))
  2546.                         {
  2547.                             Send(_T("550 could not initialize zlib, please use MODE S instead"));
  2548.                             ResetTransferstatus();
  2549.                             break;
  2550.                         }
  2551.                     }
  2552.  
  2553.                     if (!CreateTransferSocket(transfersocket))
  2554.                         break;
  2555.  
  2556.                     SendTransferinfoNotification(TRANSFERMODE_LIST, physicalDir, logicalDir);
  2557.                     Send(_T("150 Opening data channel for directory list."));
  2558.                 }
  2559.                 else
  2560.                 {
  2561.                     if (!m_transferstatus.socket)
  2562.                     {
  2563.                         CPermissions::DestroyDirlisting(pResult);
  2564.                         Send(_T("503 Bad sequence of commands."));
  2565.                         break;
  2566.                     }
  2567.                     m_transferstatus.socket->Init(pResult, TRANSFERMODE_LIST );
  2568.                     if (m_transferMode == mode_zlib)
  2569.                     {
  2570.                         if (!m_transferstatus.socket->InitZLib(m_zlibLevel))
  2571.                         {
  2572.                             Send(_T("550 could not initialize zlib, please use MODE S instead"));
  2573.                             ResetTransferstatus();
  2574.                             break;
  2575.                         }
  2576.                     }
  2577.  
  2578.                     SendTransferinfoNotification(TRANSFERMODE_LIST, physicalDir, logicalDir);
  2579.                     m_transferstatus.socket->PasvTransfer();
  2580.                 }
  2581.             }
  2582.  
  2583.         }
  2584.         break;
  2585.     case COMMAND_SITE:
  2586.         {
  2587.             CStdString cmd;
  2588.  
  2589.             args.MakeUpper();
  2590.             
  2591.             int pos = args.Find(' ');
  2592.             if (pos != -1)
  2593.             {
  2594.                 cmd = args.Left(pos);
  2595.                 args = args.Mid(pos + 1);
  2596.                 args.TrimLeft(_T(" "));
  2597.             }
  2598.             else
  2599.             {
  2600.                 cmd = args;
  2601.                 args = _T("");
  2602.             }
  2603.  
  2604.             if (cmd == _T("NAMEFMT"))
  2605.             {
  2606.                 if (args == _T("") || args == _T("1"))
  2607.                     Send(_T("200 Now using naming format \"1\""));
  2608.                 else
  2609.                     Send(_T("504 Naming format not implemented"));
  2610.                 break;
  2611.             }
  2612.             else
  2613.             {
  2614.                 Send(_T("504 Command not implemented for that parameter"));
  2615.                 break;
  2616.             }
  2617.             break;
  2618.         }
  2619.     case COMMAND_STRU:
  2620.         args.MakeUpper();
  2621.         if (args == _T("F"))
  2622.             Send(_T("200 Using file structure 'File'"));
  2623.         else
  2624.             Send(_T("504 Command not implemented for that parameter"));
  2625.         break;
  2626.     case COMMAND_CLNT:
  2627.         Send(_T("200 Don't care"));
  2628.         break;
  2629.     case COMMAND_MFMT:
  2630.         {
  2631.             int pos = args.find(' ');
  2632.             if (pos < 1)
  2633.             {
  2634.                 Send(_T("501 Syntax error"));
  2635.                 break;
  2636.             }
  2637.  
  2638.             CStdString timeval = args.Left(pos);
  2639.             args = args.Mid(pos + 1);
  2640.  
  2641.             if (timeval.GetLength() < 14)
  2642.             {
  2643.                 Send( _T("501 Syntax error") );
  2644.                 break;
  2645.             }
  2646.  
  2647.             bool numbersOnly = true;
  2648.             for (int i = 0; i < 14; i++)
  2649.             {
  2650.                 if (timeval[i] < '0' || timeval[i] > '9')
  2651.                 {
  2652.                     numbersOnly = false;
  2653.                     break;
  2654.                 }
  2655.             }
  2656.             if (!numbersOnly)
  2657.             {
  2658.                 Send( _T("501 Syntax error") );
  2659.                 break;
  2660.             }
  2661.  
  2662.             int year = (timeval[0] - '0') * 1000 +
  2663.                     (timeval[1] - '0') * 100 +
  2664.                     (timeval[2] - '0') * 10 +
  2665.                     timeval[3] - '0';
  2666.  
  2667.             int month = (timeval[4] - '0') * 10 + timeval[5] - '0';
  2668.             int day = (timeval[6] - '0') * 10 + timeval[7] - '0';
  2669.             int hour = (timeval[8] - '0') * 10 + timeval[9] - '0';
  2670.             int minute = (timeval[10] - '0') * 10 + timeval[11] - '0';
  2671.             int second = (timeval[12] - '0') * 10 + timeval[13] - '0';
  2672.  
  2673.             if (year < 1000 || month < 1 || month > 12 || day < 1 || day > 31 || hour > 23 ||
  2674.                 minute > 59 || second > 59)
  2675.             {
  2676.                 Send( _T("501 Not a valid date") );
  2677.                 break;
  2678.             }
  2679.  
  2680.             SYSTEMTIME st = {0};
  2681.             st.wYear = year;
  2682.             st.wMonth = month;
  2683.             st.wDay = day;
  2684.             st.wHour = hour;
  2685.             st.wMinute = minute;
  2686.             st.wSecond = second;
  2687.  
  2688.             FILETIME ft;
  2689.             if (!SystemTimeToFileTime(&st, &ft))
  2690.             {
  2691.                 Send( _T("501 Not a valid date") );
  2692.                 break;
  2693.             }
  2694.  
  2695.             //Unquote args
  2696.             if (!UnquoteArgs(args))
  2697.             {
  2698.                 Send( _T("501 Syntax error") );
  2699.                 break;
  2700.             }
  2701.  
  2702.             if (args == _T(""))
  2703.             {
  2704.                 Send( _T("501 Syntax error") );
  2705.                 break;
  2706.             }
  2707.  
  2708.             CStdString physicalFile, logicalFile;
  2709.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_LIST, physicalFile, logicalFile);
  2710.             if (error & PERMISSION_DENIED)
  2711.                 Send(_T("550 Permission denied"));
  2712.             else if (error & PERMISSION_INVALIDNAME)
  2713.                 Send(_T("550 Filename invalid."));
  2714.             else if (error & 2)
  2715.                 Send(_T("550 File not found"));
  2716.             else
  2717.             {
  2718.                 HANDLE hFile = CreateFile(physicalFile, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  2719.                 if (hFile == INVALID_HANDLE_VALUE)
  2720.                     Send(_T("550 Cannot access file"));
  2721.                 else
  2722.                 {
  2723.                     if (!SetFileTime(hFile, 0, 0, &ft))
  2724.                         Send(_T("550 Failed to set file modification time"));
  2725.                     else
  2726.                         Send(_T("213 modify=") + timeval.Left(14) + _T("; ") + logicalFile);
  2727.  
  2728.                     CloseHandle(hFile);
  2729.                 }
  2730.             }
  2731.         }
  2732.         break;
  2733.     case COMMAND_HASH:
  2734.         {
  2735.             if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_ENABLE_HASH))
  2736.             {
  2737.                 Send(_T("500 Syntax error, command unrecognized."));
  2738.                 break;
  2739.             }
  2740.  
  2741.             //Unquote args
  2742.             if (!UnquoteArgs(args))
  2743.             {
  2744.                 Send( _T("501 Syntax error") );
  2745.                 break;
  2746.             }
  2747.  
  2748.             CStdString physicalFile, logicalFile;
  2749.             int error = m_pOwner->m_pPermissions->CheckFilePermissions(m_status.user, args, m_CurrentServerDir, FOP_READ, physicalFile, logicalFile);
  2750.             if (error & PERMISSION_DENIED)
  2751.             {
  2752.                 Send(_T("550 Permission denied"));
  2753.                 ResetTransferstatus();
  2754.             }
  2755.             else if (error & PERMISSION_INVALIDNAME)
  2756.             {
  2757.                 Send(_T("550 Filename invalid."));
  2758.                 ResetTransferstatus();
  2759.             }
  2760.             else if (error)
  2761.             {
  2762.                 Send(_T("550 File not found"));
  2763.                 ResetTransferstatus();
  2764.             }
  2765.             else
  2766.             {
  2767.                 int hash_res = m_pOwner->GetHashThread().Hash(physicalFile, m_hash_algorithm, m_hash_id, m_pOwner);
  2768.                 if (hash_res == CHashThread::BUSY)
  2769.                     Send(_T("450 Another hash operation is already in progress."));
  2770.                 else if (hash_res != CHashThread::PENDING)
  2771.                     Send(_T("550 Failed to hash file"));
  2772.             }
  2773.         }
  2774.         break;
  2775.     default:
  2776.         Send(_T("502 Command not implemented."));
  2777.     }
  2778.  
  2779.     if (!m_RecvLineBuffer.empty())
  2780.         m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_COMMAND, m_userid);
  2781.  
  2782.     return;
  2783. }
  2784.  
  2785. void CControlSocket::ProcessTransferMsg()
  2786. {
  2787.     if (!m_transferstatus.socket)
  2788.         return;
  2789.     int status = m_transferstatus.socket->GetStatus();
  2790.  
  2791.     GetSystemTime(&m_LastCmdTime);
  2792.     if (m_transferstatus.socket)
  2793.         if (m_transferstatus.socket->GetMode()==TRANSFERMODE_SEND || m_transferstatus.socket->GetMode()==TRANSFERMODE_RECEIVE)
  2794.             GetSystemTime(&m_LastTransferTime);
  2795.  
  2796.     if (status == 2 && m_transferstatus.pasv && m_transferstatus.usedResolvedIP)
  2797.         m_pOwner->ExternalIPFailed();
  2798.     
  2799.     int mode = m_transferstatus.socket->GetMode();
  2800.     _int64 zlibBytesIn = 0;
  2801.     _int64 zlibBytesOut = 0;
  2802.     if (m_transferMode == mode_zlib)
  2803.         m_transferstatus.socket->GetZlibStats(zlibBytesIn, zlibBytesOut);
  2804.     ResetTransferstatus();
  2805.  
  2806.     if (!status)
  2807.     {
  2808.         if ((mode == TRANSFERMODE_LIST || mode == TRANSFERMODE_NLST || mode == TRANSFERMODE_SEND) && zlibBytesIn && zlibBytesOut)
  2809.         {
  2810.             if (zlibBytesIn >= zlibBytesOut)
  2811.             {
  2812.                 CString str;
  2813.                 _int64 percent = 10000 - (zlibBytesOut * 10000 / zlibBytesIn);
  2814.                 str.Format(_T("226 Transfer OK, compression saved %I64d of %I64d bytes (%I64d.%02I64d%%)"), zlibBytesIn - zlibBytesOut, zlibBytesIn, percent / 100, percent % 100);
  2815.                 Send(str);
  2816.             }
  2817.             else
  2818.             {
  2819.                 CString str;
  2820.                 _int64 percent = (zlibBytesOut * 10000 / zlibBytesIn) - 10000;
  2821.                 str.Format(_T("226 Transfer OK, unfortunately compression did increase the transfer size by %I64d bytes to %I64d bytes (%I64d.%02I64d%%)"), zlibBytesOut - zlibBytesIn, zlibBytesOut, percent / 100, percent % 100);
  2822.                 Send(str);
  2823.             }
  2824.         }
  2825.         else if (mode == TRANSFERMODE_RECEIVE && zlibBytesIn && zlibBytesOut)
  2826.         {
  2827.             if (zlibBytesOut >= zlibBytesIn)
  2828.             {
  2829.                 CString str;
  2830.                 _int64 percent = 10000 - (zlibBytesIn * 10000 / zlibBytesOut);
  2831.                 str.Format(_T("226 Transfer OK, compression saved %I64d of %I64d bytes (%I64d.%02I64d%%)"), zlibBytesOut - zlibBytesIn, zlibBytesOut, percent / 100, percent % 100);
  2832.                 Send(str);
  2833.             }
  2834.             else
  2835.             {
  2836.                 CString str;
  2837.                 _int64 percent = (zlibBytesIn * 10000 / zlibBytesOut) - 10000;
  2838.                 str.Format(_T("226 Transfer OK, unfortunately compression did increase the transfer size by %I64d bytes to %I64d bytes (%I64d.%02I64d%%)"), zlibBytesIn - zlibBytesOut, zlibBytesIn, percent / 100, percent % 100);
  2839.                 Send(str);
  2840.             }
  2841.         }
  2842.         else
  2843.             Send(_T("226 Transfer OK"));
  2844.     }
  2845.     else if (status==1)
  2846.         Send(_T("426 Connection closed; transfer aborted."));
  2847.     else if (status==2)
  2848.         Send(_T("425 Can't open data connection."));
  2849.     else if (status==3)
  2850.         Send(_T("550 can't access file."));
  2851.     else if (status==4)
  2852.     {
  2853.         Send(_T("426 Connection timed out, aborting transfer"));
  2854.         ForceClose(1);
  2855.         return;
  2856.     }
  2857.     else if (status==5)
  2858.         Send(_T("425 Can't open data connection"));
  2859.     else if (status==6)
  2860.         Send(_T("450 zlib error"));
  2861.     if (status>=0 && m_bWaitGoOffline)
  2862.         ForceClose(0);
  2863.     else if (m_bQuitCommand)
  2864.     {
  2865.         Send(_T("221 Goodbye"));
  2866.         if (CanQuit())
  2867.             ForceClose(5);
  2868.     }
  2869. }
  2870.  
  2871. CTransferSocket* CControlSocket::GetTransferSocket()
  2872. {
  2873.     return m_transferstatus.socket;
  2874. }
  2875.  
  2876. void CControlSocket::ForceClose(int nReason)
  2877. {
  2878.     if (m_transferstatus.socket)
  2879.     {
  2880.         // Don't call SendTransferInfoNotification, since connection
  2881.         // does get removed real soon.
  2882.         m_transferstatus.socket->Close();
  2883.         delete m_transferstatus.socket;
  2884.         m_transferstatus.socket = 0;
  2885.     }
  2886.     if (m_shutdown && nReason == 1)
  2887.     {
  2888.         Close();
  2889.         m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  2890.         return;
  2891.     }
  2892.  
  2893.     if (!nReason)
  2894.         Send(_T("421 Server is going offline"));
  2895.     else if (nReason == 1)
  2896.         Send(_T("421 Connection timed out."));
  2897.     else if (nReason == 2)
  2898.         Send(_T("421 No-transfer-time exceeded. Closing control connection."));
  2899.     else if (nReason == 3)
  2900.         Send(_T("421 Login time exceeded. Closing control connection."));
  2901.     else if (nReason == 4)
  2902.         Send(_T("421 Kicked by Administrator"));
  2903.     else if (nReason == 5)
  2904.     {
  2905.         // 221 Goodbye
  2906.     }
  2907.     SendStatus(_T("disconnected."), 0);
  2908.     m_shutdown = true;
  2909.     int res = ShutDown();
  2910.     if (m_pSslLayer)
  2911.     {
  2912.         if (!res && GetLastError() == WSAEWOULDBLOCK)
  2913.             return;
  2914.     }
  2915.     Close();
  2916.     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  2917. }
  2918.  
  2919. void CControlSocket::IncUserCount(const CStdString &user)
  2920. {
  2921.     int curcount=GetUserCount(user)+1;
  2922.     EnterCritSection(m_Sync);
  2923.     m_UserCount[user]=curcount;
  2924.     LeaveCritSection(m_Sync);
  2925. }
  2926.  
  2927. void CControlSocket::DecUserCount(const CStdString &user)
  2928. {
  2929.     int curcount=GetUserCount(user)-1;
  2930.     if (curcount<0)
  2931.         return;
  2932.     EnterCritSection(m_Sync);
  2933.     m_UserCount[user]=curcount;
  2934.     LeaveCritSection(m_Sync);
  2935. }
  2936.  
  2937. int CControlSocket::GetUserCount(const CStdString &user)
  2938. {
  2939.     EnterCritSection(m_Sync);
  2940.     int count=0;
  2941.     std::map<CStdString, int>::iterator iter = m_UserCount.find(user);
  2942.     if (iter!=m_UserCount.end())
  2943.         count = iter->second;
  2944.     LeaveCritSection(m_Sync);
  2945.     return count;
  2946. }
  2947.  
  2948. void CControlSocket::CheckForTimeout()
  2949. {
  2950.     if (m_antiHammeringWaitTime)
  2951.     {
  2952.         m_antiHammeringWaitTime -= 1000;
  2953.         if (m_antiHammeringWaitTime <= 0)
  2954.         {
  2955.             m_antiHammeringWaitTime = 0;
  2956.             TriggerEvent(FD_FORCEREAD);
  2957.         }
  2958.     }
  2959.     if (m_status.hammerValue > 0)
  2960.         m_status.hammerValue--;
  2961.  
  2962.     if (m_transferstatus.socket)
  2963.     {
  2964.         if (m_transferstatus.socket->CheckForTimeout())
  2965.             return;
  2966.     }
  2967.     _int64 timeout;
  2968.     if (m_shutdown)
  2969.         timeout = 3;
  2970.     else
  2971.         timeout = m_pOwner->m_pOptions->GetOptionVal(OPTION_TIMEOUT);
  2972.     if (!timeout)
  2973.         return;
  2974.     SYSTEMTIME sCurrentTime;
  2975.     GetSystemTime(&sCurrentTime);
  2976.     FILETIME fCurrentTime;
  2977.     SystemTimeToFileTime(&sCurrentTime, &fCurrentTime);
  2978.     FILETIME fLastTime;
  2979.     SystemTimeToFileTime(&m_LastCmdTime, &fLastTime);
  2980.     _int64 elapsed = ((_int64)(fCurrentTime.dwHighDateTime - fLastTime.dwHighDateTime) << 32) + fCurrentTime.dwLowDateTime - fLastTime.dwLowDateTime;
  2981.     if (elapsed > (timeout*10000000))
  2982.     {
  2983.         ForceClose(1);
  2984.         return;
  2985.     }
  2986.     if (m_status.loggedon)
  2987.     { //Transfer timeout
  2988.         _int64 nNoTransferTimeout=m_pOwner->m_pOptions->GetOptionVal(OPTION_NOTRANSFERTIMEOUT);
  2989.         if (!nNoTransferTimeout)
  2990.             return;
  2991.         SystemTimeToFileTime(&m_LastTransferTime, &fLastTime);
  2992.         elapsed = ((_int64)(fCurrentTime.dwHighDateTime - fLastTime.dwHighDateTime) << 32) + fCurrentTime.dwLowDateTime - fLastTime.dwLowDateTime;
  2993.         if (elapsed>(nNoTransferTimeout*10000000))
  2994.         {
  2995.             ForceClose(2);
  2996.             return;
  2997.         }
  2998.     }
  2999.     else
  3000.     { //Login timeout
  3001.         _int64 nLoginTimeout=m_pOwner->m_pOptions->GetOptionVal(OPTION_LOGINTIMEOUT);
  3002.         if (!nLoginTimeout)
  3003.             return;
  3004.         SystemTimeToFileTime(&m_LoginTime, &fLastTime);
  3005.         elapsed = ((_int64)(fCurrentTime.dwHighDateTime - fLastTime.dwHighDateTime) << 32) + fCurrentTime.dwLowDateTime - fLastTime.dwLowDateTime;
  3006.         if (elapsed>(nLoginTimeout*10000000))
  3007.         {
  3008.             ForceClose(3);
  3009.             return;
  3010.         }
  3011.     }
  3012. }
  3013.  
  3014. void CControlSocket::WaitGoOffline(bool wait /*=true*/)
  3015. {
  3016.     if (!wait)
  3017.     {
  3018.         m_bWaitGoOffline = FALSE;
  3019.         return;
  3020.     }
  3021.  
  3022.     if (m_transferstatus.socket)
  3023.     {
  3024.         if (!m_transferstatus.socket->Started())
  3025.             ForceClose(0);
  3026.         else
  3027.             m_bWaitGoOffline=TRUE;
  3028.     }
  3029.     else
  3030.         ForceClose(0);
  3031.  
  3032. }
  3033.  
  3034. void CControlSocket::ResetTransferstatus()
  3035. {
  3036.     if (m_transferstatus.socket)
  3037.     {
  3038.         SendTransferinfoNotification();
  3039.         delete m_transferstatus.socket;
  3040.     }
  3041.     m_transferstatus.socket = 0;
  3042.     m_transferstatus.ip = _T("");
  3043.     m_transferstatus.port = -1;
  3044.     m_transferstatus.pasv = -1;
  3045.     m_transferstatus.rest = 0;
  3046. }
  3047.  
  3048. BOOL CControlSocket::UnquoteArgs(CStdString &args)
  3049. {
  3050.     args.TrimLeft( _T(" ") );
  3051.     args.TrimRight( _T(" ") );
  3052.     int pos1 = args.Find('"');
  3053.     int pos2 = args.ReverseFind('"');
  3054.     if (pos1 == -1 && pos2 == -1)
  3055.         return TRUE;
  3056.     if (pos1 || pos2 != (args.GetLength()-1) || pos1 >= (pos2-1))
  3057.         return FALSE;
  3058.     args = args.Mid(1, args.GetLength() - 2);
  3059.     return TRUE;
  3060. }
  3061.  
  3062. void CControlSocket::OnSend(int nErrorCode)
  3063. {
  3064.     if (m_nSendBufferLen && m_pSendBuffer)
  3065.     {
  3066.         long long nLimit = GetSpeedLimit(download);
  3067.         if (!nLimit)
  3068.             return;
  3069.         int numsend;
  3070.         if (nLimit == -1 || nLimit > m_nSendBufferLen)
  3071.             numsend = m_nSendBufferLen;
  3072.         else
  3073.             numsend = static_cast<int>(nLimit);
  3074.  
  3075.         int numsent = CAsyncSocketEx::Send(m_pSendBuffer, numsend);
  3076.  
  3077.         if (numsent==SOCKET_ERROR && GetLastError() == WSAEWOULDBLOCK)
  3078.             return;
  3079.         if (!numsent || numsent == SOCKET_ERROR)
  3080.         {
  3081.             Close();
  3082.             SendStatus(_T("could not send reply, disconnected."), 0);
  3083.             m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  3084.  
  3085.             delete [] m_pSendBuffer;
  3086.             m_pSendBuffer = NULL;
  3087.             m_nSendBufferLen = 0;
  3088.  
  3089.             return;
  3090.         }
  3091.  
  3092.         if (nLimit != -1)
  3093.             m_SlQuotas[download].nTransferred += numsent;
  3094.  
  3095.         if (numsent == m_nSendBufferLen)
  3096.         {
  3097.             delete [] m_pSendBuffer;
  3098.             m_pSendBuffer = NULL;
  3099.             m_nSendBufferLen = 0;
  3100.         }
  3101.         else
  3102.         {
  3103.             char *tmp = m_pSendBuffer;
  3104.             m_pSendBuffer = new char[m_nSendBufferLen-numsent];
  3105.             memcpy(m_pSendBuffer, tmp+numsent, m_nSendBufferLen-numsent);
  3106.             delete [] tmp;
  3107.             m_nSendBufferLen -= numsent;
  3108.             TriggerEvent(FD_WRITE);
  3109.         }
  3110.     }
  3111. }
  3112.  
  3113. BOOL CControlSocket::DoUserLogin(LPCTSTR password, bool skipPass /*=false*/)
  3114. {
  3115.     CUser user;
  3116.     if (!m_pOwner->m_pPermissions->CheckUserLogin(m_status.user, password, user, skipPass))
  3117.     {
  3118.         AntiHammerIncrease(2);
  3119.         m_pOwner->AntiHammerIncrease(m_RemoteIP);
  3120.  
  3121.         if (m_pOwner->m_pAutoBanManager->RegisterAttempt(m_RemoteIP))
  3122.         {
  3123.             Send(_T("421 Temporarily banned for too many failed login attempts"));
  3124.             ForceClose(-1);
  3125.             return FALSE;
  3126.         }
  3127.  
  3128.         Send(_T("530 Login or password incorrect!"));
  3129.         return FALSE;
  3130.     }
  3131.  
  3132.     if (!user.IsEnabled())
  3133.     {
  3134.         Send(_T("530 Not logged in, user account has been disabled"));
  3135.         ForceClose(-1);
  3136.         return FALSE;
  3137.     }
  3138.     if (!user.BypassUserLimit())
  3139.     {
  3140.         int nMaxUsers = (int)m_pOwner->m_pOptions->GetOptionVal(OPTION_MAXUSERS);
  3141.         if (m_pOwner->GetGlobalNumConnections()>nMaxUsers&&nMaxUsers)
  3142.         {
  3143.             SendStatus(_T("Refusing connection. Reason: Max. connection count reached."), 1);
  3144.             Send(_T("421 Too many users are connected, please try again later."));
  3145.             ForceClose(-1);
  3146.             return FALSE;
  3147.         }
  3148.     }
  3149.     if (user.GetUserLimit() && GetUserCount(m_status.user)>=user.GetUserLimit())
  3150.     {
  3151.             CStdString str;
  3152.             str.Format(_T("Refusing connection. Reason: Max. connection count reached for the user \"%s\"."), m_status.user);
  3153.             SendStatus(str,1);
  3154.             Send(_T("421 Too many users logged in for this account. Try again later."));
  3155.             ForceClose(-1);
  3156.             return FALSE;
  3157.     }
  3158.  
  3159.     CStdString peerIP;
  3160.     UINT port = 0;
  3161.  
  3162.     BOOL bResult = GetPeerName(peerIP, port);
  3163.     if (bResult)
  3164.     {
  3165.         if (!user.AccessAllowed(peerIP))
  3166.         {
  3167.             Send(_T("521 This user is not allowed to connect from this IP"));
  3168.             ForceClose(-1);
  3169.             return FALSE;
  3170.         }
  3171.     }
  3172.     else
  3173.     {
  3174.         SendStatus(_T("Could not get peer name"), 1);
  3175.         Send(_T("421 Refusing connection. Could not get peer name."));
  3176.         ForceClose(-1);
  3177.         return FALSE;
  3178.     }
  3179.  
  3180.     int count = m_pOwner->GetIpCount(peerIP);
  3181.     if (user.GetIpLimit() && count >= user.GetIpLimit())
  3182.     {
  3183.         CStdString str;
  3184.         if (count==1)
  3185.             str.Format(_T("Refusing connection. Reason: No more connections allowed from this IP. (%s already connected once)"), peerIP.c_str());
  3186.         else
  3187.             str.Format(_T("Refusing connection. Reason: No more connections allowed from this IP. (%s already connected %d times)"), peerIP.c_str(), count);
  3188.         SendStatus(str, 1);
  3189.         Send(_T("421 Refusing connection. No more connections allowed from your IP."));
  3190.         ForceClose(-1);
  3191.         return FALSE;
  3192.     }
  3193.  
  3194.     m_CurrentServerDir = m_pOwner->m_pPermissions->GetHomeDir(m_status.user);
  3195.     if (m_CurrentServerDir == _T(""))
  3196.     {
  3197.         Send(_T("550 Could not get home dir!"));
  3198.         ForceClose(-1);
  3199.         return FALSE;
  3200.     }
  3201.  
  3202.     m_status.ip = peerIP;
  3203.  
  3204.     count = GetUserCount(user.user);
  3205.     if (user.GetUserLimit() && count >= user.GetUserLimit())
  3206.     {
  3207.         CStdString str;
  3208.         str.Format(_T("Refusing connection. Reason: Maximum connection count (%d) reached for this user"), user.GetUserLimit());
  3209.         SendStatus(str, 1);
  3210.         str.Format(_T("421 Refusing connection. Maximum connection count reached for the user '%s'"), user.user);
  3211.         Send(str);
  3212.         ForceClose(-1);
  3213.         return FALSE;
  3214.     }
  3215.  
  3216.     m_pOwner->IncIpCount(peerIP);
  3217.     IncUserCount(m_status.user);
  3218.     m_status.loggedon = TRUE;
  3219.  
  3220.     GetSystemTime(&m_LastTransferTime);
  3221.  
  3222.     m_pOwner->m_pPermissions->AutoCreateDirs(m_status.user);
  3223.  
  3224.     t_connectiondata_changeuser *conndata = new t_connectiondata_changeuser;
  3225.     t_connop *op = new t_connop;
  3226.     op->data = conndata;
  3227.     op->op = USERCONTROL_CONNOP_CHANGEUSER;
  3228.     op->userid = m_userid;
  3229.     conndata->user = m_status.user;
  3230.  
  3231.     m_pOwner->SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  3232.  
  3233.     return TRUE;
  3234. }
  3235.  
  3236. void CControlSocket::Continue()
  3237. {
  3238.     if (m_SlQuotas[download].bContinue)
  3239.     {
  3240.         TriggerEvent(FD_WRITE);
  3241.         if (m_transferstatus.socket && m_transferstatus.socket->Started())
  3242.             m_transferstatus.socket->TriggerEvent(FD_WRITE);
  3243.         m_SlQuotas[download].bContinue = false;
  3244.     }
  3245.  
  3246.     if (m_SlQuotas[upload].bContinue)
  3247.     {
  3248.         TriggerEvent(FD_READ);
  3249.         if (m_transferstatus.socket && m_transferstatus.socket->Started())
  3250.             m_transferstatus.socket->TriggerEvent(FD_READ);
  3251.         m_SlQuotas[upload].bContinue = false;
  3252.     }
  3253. }
  3254.  
  3255. long long CControlSocket::GetSpeedLimit(sltype mode)
  3256. {
  3257.     CUser user;
  3258.     long long nLimit = -1;
  3259.     if (m_status.loggedon && m_pOwner->m_pPermissions->GetUser(m_status.user, user))
  3260.     {
  3261.         nLimit = user.GetCurrentSpeedLimit(mode);
  3262.     }
  3263.     if (nLimit > 0)
  3264.     {
  3265.         nLimit *= 100;
  3266.         if (m_SlQuotas[mode].nTransferred >= nLimit)
  3267.         {
  3268.             m_SlQuotas[mode].bContinue = TRUE;
  3269.             return 0;
  3270.         }
  3271.         else
  3272.             nLimit -= m_SlQuotas[mode].nTransferred;
  3273.     }
  3274.     else
  3275.         nLimit = -1;
  3276.     if (user.BypassServerSpeedLimit(mode))
  3277.         m_SlQuotas[mode].bBypassed = TRUE;
  3278.     else if (m_SlQuotas[mode].nBytesAllowedToTransfer != -1)
  3279.     {
  3280.         if (nLimit == -1 || nLimit > (m_SlQuotas[mode].nBytesAllowedToTransfer - m_SlQuotas[mode].nTransferred))
  3281.             nLimit = m_SlQuotas[mode].nBytesAllowedToTransfer - m_SlQuotas[mode].nTransferred;
  3282.     }
  3283.  
  3284.     if (!nLimit)
  3285.         m_SlQuotas[mode].bContinue = TRUE;
  3286.  
  3287.     return nLimit;
  3288. }
  3289.  
  3290. BOOL CControlSocket::CreateTransferSocket(CTransferSocket *pTransferSocket)
  3291. {
  3292.     /* Create socket
  3293.      * First try control connection port - 1, if that fails try
  3294.      * control connection port + 1. If that fails as well, let
  3295.      * the OS decide.
  3296.      */
  3297.     bool bFallback = false;
  3298.     BOOL bCreated = FALSE;
  3299.  
  3300.     // Fix: Formerly, the data connection would always be opened using the server's default (primary) IP.
  3301.     // This would cause Windows Firewall to freak out if control connection was opened on a secondary IP.
  3302.     // When using Active FTP behind Windows Firewall, no connection could be made. This fix ensures the data
  3303.     // socket is on the same IP as the control socket.
  3304.     CStdString controlIP;
  3305.     UINT controlPort = 0;
  3306.     BOOL bResult = this->GetSockName(controlIP, controlPort);
  3307.  
  3308.     if (bResult)
  3309.     {
  3310.         // Try create control conn. port - 1
  3311.         if (controlPort > 1)
  3312.             if (pTransferSocket->Create(controlPort - 1, SOCK_STREAM, FD_CONNECT, controlIP, m_transferstatus.family, true))
  3313.                 bCreated = TRUE;
  3314.     }
  3315.     if (!bCreated)
  3316.     {
  3317. creation_fallback:
  3318.         bFallback = true;
  3319.         // Let the OS find a valid port
  3320.         if (!pTransferSocket->Create(0, SOCK_STREAM, FD_CONNECT, controlIP, m_transferstatus.family, true))
  3321.         {
  3322.             // Give up
  3323.             Send(_T("421 Could not create socket."));
  3324.             ResetTransferstatus();
  3325.             return FALSE;
  3326.         }
  3327.     }
  3328.     if (m_pGssLayer && m_pGssLayer->AuthSuccessful())
  3329.         m_transferstatus.socket->UseGSS(m_pGssLayer);
  3330.  
  3331.     if (pTransferSocket->Connect(m_transferstatus.ip, m_transferstatus.port) == 0)
  3332.     {
  3333.         if (!bFallback && GetLastError() == WSAEADDRINUSE)
  3334.         {
  3335.             pTransferSocket->Close();
  3336.             goto creation_fallback;
  3337.         }
  3338.  
  3339.         if (GetLastError() != WSAEWOULDBLOCK)
  3340.         {
  3341.             Send(_T("425 Can't open data connection"));
  3342.             ResetTransferstatus();
  3343.             return FALSE;
  3344.         }
  3345.     }
  3346.  
  3347.     if (m_pSslLayer && m_bProtP)
  3348.         pTransferSocket->UseSSL(m_pSslLayer->GetContext());
  3349.  
  3350.     return TRUE;
  3351. }
  3352.  
  3353. bool CControlSocket::CheckIpForZlib()
  3354. {
  3355.     CStdString peerIP;
  3356.     UINT port = 0;
  3357.     BOOL bResult = GetPeerName(peerIP, port);
  3358.     if (!bResult)
  3359.         return false;
  3360.  
  3361.     if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_MODEZ_ALLOWLOCAL) && !IsRoutableAddress(peerIP))
  3362.         return false;
  3363.  
  3364.     CStdString ips = m_pOwner->m_pOptions->GetOption(OPTION_MODEZ_DISALLOWED_IPS);
  3365.     ips += " ";
  3366.  
  3367.     int pos = ips.Find(' ');
  3368.     while (pos != -1)
  3369.     {
  3370.         CStdString blockedIP = ips.Left(pos);
  3371.         ips = ips.Mid(pos + 1);
  3372.         pos = ips.Find(' ');
  3373.  
  3374.         if (MatchesFilter(blockedIP, peerIP))
  3375.             return false;
  3376.     }
  3377.  
  3378.     return true;
  3379. }
  3380.  
  3381. void CControlSocket::AntiHammerIncrease(int amount /*=1*/)
  3382. {
  3383.     if (m_status.hammerValue < 8000)
  3384.         m_status.hammerValue += amount * 200;
  3385.  
  3386.     if (m_status.hammerValue > 2000)
  3387.         m_antiHammeringWaitTime += 1000 * (int)pow(1.3, (m_status.hammerValue / 400) - 5);
  3388. }
  3389.  
  3390. void CControlSocket::SendTransferinfoNotification(const char transfermode, const CStdString& physicalFile, const CStdString& logicalFile, __int64 startOffset, __int64 totalSize)
  3391. {
  3392.     t_connop *op = new t_connop;
  3393.     op->op = USERCONTROL_CONNOP_TRANSFERINIT;
  3394.     op->userid = m_userid;
  3395.  
  3396.     t_connectiondata_transferinfo *conndata = new t_connectiondata_transferinfo;
  3397.     conndata->transferMode = transfermode;
  3398.     conndata->physicalFile = physicalFile;
  3399.     conndata->logicalFile = logicalFile;
  3400.     conndata->startOffset = startOffset;
  3401.     conndata->totalSize = totalSize;
  3402.     op->data = conndata;
  3403.  
  3404.     m_pOwner->SendNotification(FSM_CONNECTIONDATA, (LPARAM)op);
  3405. }
  3406.  
  3407. int CControlSocket::OnLayerCallback(std::list<t_callbackMsg>& callbacks)
  3408. {
  3409.     for (std::list<t_callbackMsg>::iterator iter = callbacks.begin(); iter != callbacks.end(); iter++)
  3410.     {
  3411.         if (m_pSslLayer && iter->pLayer == m_pSslLayer)
  3412.         {
  3413.             if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC && iter->nParam1 == SSL_INFO && iter->nParam2 == SSL_INFO_ESTABLISHED)
  3414.                 SendStatus(_T("SSL connection established"), 0);
  3415.             else if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC && iter->nParam1 == SSL_INFO && iter->nParam2 == SSL_INFO_SHUTDOWNCOMPLETE)
  3416.             {
  3417.                 if (m_shutdown)
  3418.                 {
  3419.                     delete [] iter->str;
  3420.                     Close();
  3421.                     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  3422.                     return 0;
  3423.                 }
  3424.                 if (!m_bQuitCommand)
  3425.                 {
  3426.                     delete [] iter->str;
  3427.                     continue;
  3428.                 }
  3429.  
  3430.                 do
  3431.                 {
  3432.                     delete [] iter->str;
  3433.                     iter++;
  3434.                 } while (iter != callbacks.end());
  3435.  
  3436.                 ForceClose(5);
  3437.  
  3438.                 return 0;
  3439.             }
  3440.         }
  3441.         else if (iter->nType == LAYERCALLBACK_LAYERSPECIFIC && iter->nParam1 == SSL_VERBOSE_WARNING)
  3442.         {
  3443.             if (iter->str)
  3444.             {
  3445.                 CStdString str = "SSL warning: ";
  3446.                 str += iter->str;
  3447.  
  3448.                 SendStatus(str, 1);
  3449.             }
  3450.         }
  3451.         delete [] iter->str;
  3452.     }
  3453.     return 0;//CAsyncSocketEx::OnLayerCallback(pLayer, nType, nParam1, nParam2);
  3454. }
  3455.  
  3456. bool CControlSocket::InitImplicitSsl()
  3457. {
  3458.     m_pSslLayer = new CAsyncSslSocketLayer;
  3459.     int res = AddLayer(m_pSslLayer) ? 1 : 0;
  3460.     if (!res)
  3461.     {
  3462.         delete m_pSslLayer;
  3463.         m_pSslLayer = 0;
  3464.         return false;
  3465.     }
  3466.  
  3467.     CString error;
  3468. #ifdef _UNICODE
  3469.     res = m_pSslLayer->SetCertKeyFile(ConvToLocal(m_pOwner->m_pOptions->GetOption(OPTION_SSLCERTFILE)), ConvToLocal(m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYFILE)), ConvToLocal(m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYPASS)), &error);
  3470. #else
  3471.     res = m_pSslLayer->SetCertKeyFile(m_pOwner->m_pOptions->GetOption(OPTION_SSLCERTFILE), m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYFILE), m_pOwner->m_pOptions->GetOption(OPTION_SSLKEYPASS), &error);
  3472. #endif
  3473.     if (res == SSL_FAILURE_LOADDLLS)
  3474.         SendStatus(_T("Failed to load SSL libraries"), 1);
  3475.     else if (res == SSL_FAILURE_INITSSL)
  3476.         SendStatus(_T("Failed to initialize SSL libraries"), 1);
  3477.     else if (res == SSL_FAILURE_VERIFYCERT)
  3478.     {
  3479.         if (error != _T(""))
  3480.             SendStatus(error, 1);
  3481.         else
  3482.             SendStatus(_T("Failed to set certificate and private key"), 1);
  3483.     }
  3484.     if (res)
  3485.     {
  3486.         RemoveAllLayers();
  3487.         delete m_pSslLayer;
  3488.         m_pSslLayer = NULL;
  3489.         Send(_T("431 Could not initialize SSL connection"), 1);
  3490.         return false;
  3491.     }
  3492.  
  3493.     int code = m_pSslLayer->InitSSLConnection(false);
  3494.     if (code == SSL_FAILURE_LOADDLLS)
  3495.         SendStatus(_T("Failed to load SSL libraries"), 1);
  3496.     else if (code == SSL_FAILURE_INITSSL)
  3497.         SendStatus(_T("Failed to initialize SSL library"), 1);
  3498.  
  3499.     if (!code)
  3500.         return true;
  3501.  
  3502.     RemoveAllLayers();
  3503.     delete m_pSslLayer;
  3504.     m_pSslLayer = NULL;
  3505.     Send(_T("431 Could not initialize SSL connection"));
  3506.  
  3507.     //Close socket
  3508.     Close();
  3509.     SendStatus(_T("disconnected."), 0);
  3510.     m_pOwner->PostThreadMessage(WM_FILEZILLA_THREADMSG, FTM_DELSOCKET, m_userid);
  3511.  
  3512.     return false;
  3513. }
  3514.  
  3515. bool CControlSocket::CanQuit()
  3516. {
  3517.     if (m_pSslLayer)
  3518.         return false;
  3519.     return true;
  3520. }
  3521.  
  3522. CStdString CControlSocket::GetPassiveIP()
  3523. {
  3524.     //Get the ip of the control socket
  3525.     CStdString localIP;
  3526.     UINT localPort;
  3527.     BOOL bValidSockAddr = GetSockName(localIP, localPort);
  3528.  
  3529.     //Get peer ip
  3530.     CStdString peerIP;
  3531.     UINT peerPort = 0;
  3532.     BOOL bResult = GetPeerName(peerIP, peerPort);
  3533.     if (bResult)
  3534.     {
  3535.         if (m_pOwner->m_pOptions->GetOptionVal(OPTION_NOEXTERNALIPONLOCAL) && !IsRoutableAddress(peerIP))
  3536.         {
  3537.             // Remote IP address from an unroutable subnet
  3538.             
  3539.             // Inside a NAT-in-NAT environment, two different unroutable address ranges are used.
  3540.             // If remote address comes from a different unroutable subnet, don't use local
  3541.             // address.
  3542.             // Note that in a NAT-in-NAT environment, the external IP address specified will either
  3543.             // be the worldwide one or the NAT one. Either external or single-NATed users won't be able
  3544.             // to use passive mode.
  3545.             m_transferstatus.usedResolvedIP = false;
  3546.  
  3547.             if (!bValidSockAddr)
  3548.                 return _T("");
  3549.             return localIP;
  3550.         }
  3551.     }
  3552.  
  3553.     if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
  3554.     {
  3555.         CStdString pasvIP = m_pOwner->GetExternalIP(localIP);
  3556.         if (pasvIP != _T("") && pasvIP != localIP)
  3557.         {
  3558.             m_transferstatus.usedResolvedIP = true;
  3559.             return pasvIP;
  3560.         }
  3561.     }
  3562.  
  3563.     m_transferstatus.usedResolvedIP = false;
  3564.  
  3565.     if (!bValidSockAddr)
  3566.         return _T("");
  3567.  
  3568.     return localIP;
  3569. }
  3570.  
  3571. void CControlSocket::ParseMlstOpts(CStdString args)
  3572. {
  3573.     if (args == _T(""))
  3574.     {
  3575.         for (int i = 0; i < 4; i++)
  3576.             m_facts[i] = false;
  3577.         Send(_T("200 MLST OPTS"));
  3578.         return;
  3579.     }
  3580.     if (args[0] != ' ')
  3581.     {
  3582.         Send(_T("501 Invalid MLST options"));
  3583.         return;
  3584.     }
  3585.     args = args.Mid(1);
  3586.     if (args.Find(' ') != -1)
  3587.     {
  3588.         Send(_T("501 Invalid MLST options"));
  3589.         return;
  3590.     }
  3591.  
  3592.     bool facts[4] = {0};
  3593.     while (args != _T(""))
  3594.     {
  3595.         int pos = args.Find(';');
  3596.         if (pos < 1)
  3597.         {
  3598.             Send(_T("501 Invalid MLST options"));
  3599.             return;
  3600.         }
  3601.  
  3602.         CStdString fact = args.Left(pos);
  3603.         args = args.Mid(pos + 1);
  3604.  
  3605.         if (fact == _T("TYPE"))
  3606.             facts[fact_type] = true;
  3607.         else if (fact == _T("SIZE"))
  3608.             facts[fact_size] = true;
  3609.         else if (fact == _T("MODIFY"))
  3610.             facts[fact_modify] = true;
  3611.         //else if (fact == _T("PERM"))
  3612.         //    facts[fact_perm] = true;
  3613.     }
  3614.  
  3615.     for (int i = 0; i < 4; i++)
  3616.         m_facts[i] = facts[i];
  3617.  
  3618.     CStdString factstr;
  3619.     if (facts[fact_type])
  3620.         factstr += _T("type;");
  3621.     if (facts[fact_size])
  3622.         factstr += _T("size;");
  3623.     if (facts[fact_modify])
  3624.         factstr += _T("modify;");
  3625.     if (facts[fact_perm])
  3626.         factstr += _T("perm;");
  3627.     
  3628.     CStdString result = _T("200 MLST OPTS");
  3629.     if (factstr != _T(""))
  3630.         result += _T(" ") + factstr;
  3631.  
  3632.     Send(result);
  3633. }
  3634.  
  3635. void CControlSocket::ParseHashOpts(CStdString args)
  3636. {
  3637.     if (args == _T(""))
  3638.     {
  3639.         switch (m_hash_algorithm)
  3640.         {
  3641.         case CHashThread::MD5:
  3642.             Send(_T("200 MD5"));
  3643.             break;
  3644.         case CHashThread::SHA512:
  3645.             Send(_T("200 SHA-512"));
  3646.             break;
  3647.         default:
  3648.             Send(_T("200 SHA-1"));
  3649.             break;
  3650.         }
  3651.         return;
  3652.     }
  3653.     if (args[0] != ' ')
  3654.     {
  3655.         Send(_T("501 Invalid HASH options"));
  3656.         return;
  3657.     }
  3658.     args = args.Mid(1);
  3659.     if (args.Find(' ') != -1)
  3660.     {
  3661.         Send(_T("501 Invalid HASH options"));
  3662.         return;
  3663.     }
  3664.  
  3665.     if (args == _T("SHA-1"))
  3666.     {
  3667.         m_hash_algorithm = CHashThread::SHA1;
  3668.         Send(_T("200 Hash algorithm set to SHA-1"));
  3669.     }
  3670.     else if (args == _T("SHA-512"))
  3671.     {
  3672.         m_hash_algorithm = CHashThread::SHA512;
  3673.         Send(_T("200 Hash algorithm set to SHA-512"));
  3674.     }
  3675.     else if (args == _T("MD5"))
  3676.     {
  3677.         m_hash_algorithm = CHashThread::MD5;
  3678.         Send(_T("200 Hash algorithm set to MD5"));
  3679.     }
  3680.     else
  3681.         Send(_T("501 Unknown algorithm"));
  3682. }
  3683.  
  3684. void CControlSocket::ProcessHashResult(int hash_id, int res, CHashThread::_algorithm alg, const CStdString& hash, const CStdString& file)
  3685. {
  3686.     if (hash_id != m_hash_id)
  3687.         return;
  3688.     
  3689.     m_hash_id = 0;
  3690.  
  3691.     if (res == CHashThread::BUSY)
  3692.         Send(_T("450 Another hash operation is already in progress."));
  3693.     else if (res == CHashThread::FAILURE_OPEN)
  3694.         Send(_T("550 Failed to open file"));
  3695.     else if (res == CHashThread::FAILURE_READ)
  3696.         Send(_T("550 Could not read from file"));
  3697.     else
  3698.     {
  3699.         CStdString algname;
  3700.         switch (alg)
  3701.         {
  3702.         case CHashThread::SHA1:
  3703.             algname = "SHA-1";
  3704.             break;
  3705.         case CHashThread::SHA512:
  3706.             algname = "SHA-512";
  3707.             break;
  3708.         case CHashThread::MD5:
  3709.             algname = "MD5";
  3710.             break;
  3711.         }
  3712.         Send(_T("213 ") + algname + _T(" ") + hash + _T(" ") + file);
  3713.     }
  3714. }
  3715.